Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How select a file from one branch when resolving conflict during git rebase?

Tags:

git

Given a git repo with two branches master and feature. When rebasing the feature branch on top of master using rebase master lets say that file a.txt contains a conflict that needs to be resolved before the rebase can continue.

I know that I can resolve the conflict in three steps:

  1. open a.txt in my editor manually resolve the conflict
  2. call git add a.txt to tell git I have manually resolved the conflict
  3. call git rebase --continue move the rebase forward

Is there a way to avoid step 1 by telling git that I want the version of the file from the master branch or I want the version of the file from feature branch without having to do steps 1 and 2 above.

like image 550
ams Avatar asked Jan 31 '14 21:01

ams


3 Answers

Yes. In fact, there's more than one way to do it.

The rebase and merge (and cherry-pick, for that matter) commands all take the same strategy and -X flags to pass to the underlying git merge machinery. For the recursive strategy, -Xours and -Xtheirs choose one or the other "sides" of files in the case of a file modified in both branches being merged.

Or—this is quite different—in the cases when merge stops with a conflict, you can use git checkout with the --ours or --theirs flags, to pick the version from one side or the other. (You can do this with other commands; here, I'll stick with --ours and --theirs as these match the arguments to the commands that use the merge machinery.)

This is of course different because you can switch up the choices:

$ git checkout main
Switched to branch 'main'
$ git merge branch
... conflicts in files A and B ...
$ git checkout --ours -- A    # takes main:A
$ git checkout --theirs -- B  # takes branch:B

Note that this is quite different from the "ours strategy" (the above shows the "recursive strategy with the ours option"). With the "ours strategy", something completely different occurs. Let's start without it, doing the same merge again:

$ git checkout main && git merge branch
... conflicts ...
$ git checkout --ours -- A B  # take main:A and main:B

Let's say there's a third file, C, that git can merge on its own. When you do the above, git merges C and you take main:A and main:B. If you were to use git merge --strategy=ours branch, though, git would take main:A, main:B, and main:C. It would discard the branch:C changes rather than automatically merging them.

I've used git merge above because it makes the "ours" and "theirs" stuff "work right". I dislike the way git names these, though, because when you're doing a rebase, the ours/theirs version get swapped around, because rebase works by changing to the "other" branch and doing a series of cherry-picks. That is:

$ git checkout mine; git rebase theirs

works underneath by doing the (very) rough equivalent of:

$ git checkout theirs; git cherry-pick theirs..mine

and then afterward, shuffling the branch labels around so that branch theirs does not actually move. (It's not nearly that bad internally :-) but it does manage to make --ours mean "theirs" and --theirs mean "ours", which is pretty bad externally.)

like image 70
torek Avatar answered Oct 30 '22 12:10

torek


You can use:

git checkout --ours -- path/to/file

Or:

git checkout --theirs -- path/to/file

...during a merge or rebase to choose a particular version of a conflicting file; because rebasing is a little strange, --theirs in this case would be feature's version, --ours would be master's.

like image 9
Ash Wilson Avatar answered Oct 30 '22 12:10

Ash Wilson


I believe that what you are looking for, which will get rid of all three steps, is

git rebase master -X theirs

which will automatically resolve conflicts in favour of feature (the currently checked out branch), or

git rebase master -X ours

The sense of ours and theirs is counterintuitive as arguments to rebase, as noted in the description of the option at http://git-scm.com/docs/git-rebase

like image 2
GreenAsJade Avatar answered Oct 30 '22 13:10

GreenAsJade