2

In our git workflow (using GitHub Enterprise) we have feature branches that have to be merged into two different and independent branches (dev and master). That works well as long as there is no merge conflict.

For example, two feature branches merged into dev have conflicting changes for file F. Both changes should end up in dev, but I don't want dozens of unrelated changes from dev getting merged into my feature branch because they would end up later in master and that's not okay.

What we tried:

  • GitHub's editor lets you fix the issue easily but at the same time it also quietly merges the target branch (dev) into the source (the feature branch). I haven't found a way to stop it from doing so.
  • There seems to be no way to use git merge on a single file.
  • git checkout dev --patch -- F gives you a horrible interface based on vim which I don't dare to propose to my team.
  • There's also a --merge option in git checkout which simply seems to overwrite changes.
  • git checkout --conflict=diff3 had exactly the same result.

The best we came up with so far was to do the changes in GitHub and to revert the merge in the feature branch afterwards but that doesn't look like a clean and solid solution to me.

wortwart
  • 3,139
  • 27
  • 31
  • "*…interface based on vim…*" You can change difftool/editor/mergetool at any time. Use any horrible ones you love. – phd Aug 25 '21 at 10:36
  • @phd It's not so much an issue with vim but "Apply this hunk to index and worktree [y,n,q,a,d,e,?]?" doesn't look like a failproof workflow solution. – wortwart Aug 26 '21 at 15:34

2 Answers2

4

The problem is, you do not merge files in git. You merge commits. Therefore, whatever the commit contains, it is supposed to be included in the merge except you can hand pick and edit final contents of the merge. But that is supposed to be used for resolving conflicts and that kind of staff.

Maybe you can split your commit in the feature branch into two commits, so that the first commit will only contain the changes to the file in question, and the second commit will add the rest. And you can only merge up to that commit.

  • Splitting the merge could be a solution, yes. I'll have to test if this works better than reverting the pre-merge commit. – wortwart Aug 26 '21 at 15:45
1

Merging a file requires three versions, not two:

  • You need a "left side" or --ours or LOCAL version, whatever you'd like to call it. That's the one with your changes.
  • You need a "right side" or --theirs or REMOTE or other version: again, whatever you'd like to call it is not that important; it's the version of the file with their changes, whoever "they" are.
  • Finally—or really, first—you need a common starting point version of this file. That's the version both you and they started from, before you made your changes, and they made their changes.

You get these files from anywhere you'd like. When you run git merge, Git gets all three of these for you:

  • Your version is the current one, in your current commit, as seen in your working tree. You select this commit with git checkout or git switch.
  • Their version is the version of the file in the branch or commit you name on your command line: git merge theirbranch, for instance, uses the name theirbranch to look up the commit hash ID of the commit that contains their version of this file.
  • Git locates the merge base copy—the common starting point—automatically, using the commit graph. See Pretty Git branch graphs. You can have Git compute the merge base(s)—there can be more than one, though if there are several, things get a little sticky—using the git merge-base program, provided you know the right two commit hash IDs, or have names for them: Git itself runs git merge-base --all HEAD theirbranch, for instance.

If you'd like to merge just one file, you will have to locate all three copies of the file in some manner. Exactly how you do that is up to you. Then you simply use the git merge-file command, as described in its documentation.

torek
  • 448,244
  • 59
  • 642
  • 775