Prevent merge on master branch for a type of file - Git

本小妞迷上赌 提交于 2019-12-11 03:56:23

问题


I have a git repo with a release branch ("master") and some other branches for develop purposes.

Being an embedded project, there are some .tbl files which are generated or modified on every compilation. I need to keep the tbl files in the master branch not modified (unless there is a new release) and therefore prevent merging with other branches from modifying those tbl files.

I already tried declaring tbl files as binary or using *.tbl merge=ours but as specified in https://git-scm.com/docs/git-merge this only work in case of conflict.

Has anyone ever run across a similar situation?


回答1:


Git has no merge strategy for this case.

Short of writing your own merge strategy—git merge -s ArenaLor will invoke git-merge-ArenaLor, and you'd have to write that command but then it would do whatever you wanted—there is, as you observed, no way to get Git to do a normal three-way merge on most files but to always keep a particular version of a particular set of files in place.

Fundamentally, most merge strategies do the following:

  1. Identify the merge-base commit. Let's call this commit B for convenience. B has a bunch of files saved as snapshots; from here, the other two branches diverge.
  2. Diff the merge base against each branch tip, to find which files are changed in which branches. For illustration, it's simplest to call the two branch tips L and R, for Left and Right, or Local and Remote, or Ours and Theirs (there is no L in the word "ours" but this is how Git works with the usual recursive and resolve strategies).
  3. Build the new commit-to-make by taking each file from B (no change in either branch), L (file is changed only in our local/left-side branch), R (file is changed only in their remote/right-side branch), or—if the file is changed in both of the two branch-tip commits—by combining the changes.

The *.tbl merge=ours option in a .gitattributes file affects only step 3, and then only if the file is changed in both branch-tip commits. That is, a merge driver is only run if Git has to combine changes. It doesn't matter whether the changes have conflicts; what matters is that both L and R have changed some file F with respect to what was in the merge base commit B.

These decisions are all made by the merge strategy, though, so if you write your own, you can make your own decisions. Note that the -s ours strategy is quite different: instead of doing the above three steps, it does this one step:

  1. Take all the files from L. We don't even need to find B, or look at the contents of R. Just keep whatever's in the index right now and make a merge commit with parent 1 = L and parent 2 = R.

That does what you want for your *.tbl files, but is wrong for all your other files, so it's not suitable here.




回答2:


You can set *.tbl merge=ours in .gitattributes file, and add global setting:

git config --global merge.ours.driver true

It only keep the version of *.tbl file on master branch for part of situations (as the first two situations as below).

When you merge other branches into master, there has three situations for the *.tbl file:

  • Has conflict for the *.tbl file when merging: that means the version of *.tbl file in other branches is different from the version in master branch. Since you have set merge strategies for the *.tbl as ours. Then the version of *.tbl on master branch will be ketp.
  • Did not change the *.tbl file on both sides: that means both the versions of *.tbl file on master the other branches are same, so don’t worry the *.tbl file on master branch is overwritten.
  • Change the *.tbl file only on other branches side: this will overwrite the *.tbl file with the version of the other branches since git merge use the recursive merge strategy. So you need to switch *.tbl file with the version on master branch. So you can use below commands:

    git merge branchname
    git checkout HEAD~ *.tbl
    git commit -m 'switch the file as the version on master'
    

BTW, if the *.tbl file is not necessary to version control on non-master branches, you can only manage the file on master branch.


Or there is another option you can refer: manage the file *.tbl in a separate branch (such tbl branch).

Even the *.tbl file may be overwritten on master branch, the version on tbl branch should be correct. When you need a new release, you can checkout the version from tbl branch to master branch:

git checkout master
git checkout tbl *.tbl 
git commit -m 'recovery the version as last release'

Then you can prepare for the new release.

After releasing on master branch you can update the file on tbl branch:

git checkout tbl
git checkout master *.tbl
git commit -m 'update the file with new release version on tbl branch'


来源:https://stackoverflow.com/questions/46172688/prevent-merge-on-master-branch-for-a-type-of-file-git

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!