How to keep only head changes in a git rebase

21,162

Solution 1

If you are willing to start the rebase over (git rebase --abort), then this should do what you need:

git rebase -X ours upstream

where upstream is the branch you are rebasing onto.

As noted in this answer and elsewhere, the ours vs. theirs labels are slightly more confusing for rebasing than for merging. After starting a rebase, Git creates an anonymous branch and starts applying commits to it. Since ours means "keep changes from the current branch", that current branch will be HEAD, which contains upstream and any changes already applied by rebase.

Solution 2

For the sake of completeness, this is what I learn from the previous answer and comments in current Q&A (credit goes to their authors):

  • If you are willing to start over and choose same side for ALL the commits, the current chosen answer git rebase --abort and then git rebase -X ours upstream can do the trick.
  • But I guess in practice you won't want to blindly use either ours or theirs without looking into each commits. You would want to make a case-by-case decision for each commit, when "in the middle of a lengthy rebase". So, your actual options will be:

    1. To use the upstream:

      git checkout --ours path/to/a/specific/file
      git add path/to/a/specific/file
      

      or even better, in this case you simply use this:

      git reset HEAD path/to/a/specific/file
      
    2. Use your feature branch:

      git checkout --theirs path/to/a/specific/file
      
    3. or do it in the manual way to address each <<<< ... ==== ... >>>> in your editor.

PS: The ours and theirs have special meaning when doing rebase.:

Note that during git rebase and git pull --rebase, ours and theirs may appear swapped; --ours gives the version from the branch the changes are rebased onto, while --theirs gives the version from the branch that holds your work that is being rebased.

This is because rebase is used in a workflow that treats the history at the remote as the shared canonical one, and treats the work done on the branch you are rebasing as the third-party work to be integrated, and you are temporarily assuming the role of the keeper of the canonical history during the rebase. As the keeper of the canonical history, you need to view the history from the remote as ours (i.e. "our shared canonical history"), while what you did on your side branch as theirs (i.e. "one contributor’s work on top of it").

Share:
21,162
Smee
Author by

Smee

Updated on April 22, 2020

Comments

  • Smee
    Smee about 4 years

    I'm currently in the middle of a lengthy rebase going through a dozen or so commits. I've structured things in my dev process such that only the changes from HEAD is what I want to keep - all other conflicts (e.g. commit hash b06a1dd) should be deleted.

    Is there a way to simply remove all changes related to the >>>>>>> b06a1dd and keep the changes that Git will label <<<<<<< HEAD in one fell swoop, so I don't have to keep typing git rebase --continue, deal with more conflicts from more commit hashes, and only keep the HEAD changes?

  • Smee
    Smee almost 8 years
    This is exactly what I was looking for. Thank you!
  • Alexandro Sánchez
    Alexandro Sánchez over 6 years
    Is there any way of picking ours or theirs changes at specific conflicts when there's already a rebase under way?
  • thanhpk
    thanhpk about 6 years
    @AlexandroSánchez you can use git checkout --ours, just remember that ours and theirs are swapped during rebase, see git-scm.com/docs/git-checkout#git-checkout---ours
  • Jose Paez
    Jose Paez about 4 years
    It failed miserably for me, I used the "git reset HEAD path/to/a/specific/file" for every file, finished and went to start the server and got "There was an error parsing Gemfile: syntax error, unexpected <<, expecting keyword_end - <<<<<<< HEAD...."
  • Jose Paez
    Jose Paez about 4 years
    I get forced to cherry pick: The previous cherry-pick is now empty, possibly due to conflict resolution. If you wish to commit it anyway, use: git commit --allow-empty Otherwise, please use 'git cherry-pick --skip' interactive rebase in progress; onto c0f562d Last commands done (13 commands done): pick f3db26ce36 Bluh pick bb461e5aaa Bloh Next commands to do (35 remaining commands): pick fd1c6d5087 Blih pick 6db57302e4 Bleh You are currently rebasing branch 'my_branch' on 'c0f562d755' nothing to commit, working tree clean Could not apply bb461e5aaa... Blah
  • RayLuo
    RayLuo about 4 years
    @JosePaez Sorry to hear that. Unless you have the mood to redo it, reproduce it, and pinpoint the reason, it is hard to give a specific comment here. It could be an accidental git add path/to/that/Gemfile, or some equivalent.
  • Scott Weldon
    Scott Weldon about 4 years
    @JosePaez: I'm not sure what the context here is or what your question is. AFAICT it doesn't seem to be the same as this question though, so if you're still having this problem, please ask a new question, linking to this one if it's related. If you do ask a new question, feel free to post the link here so I'll see it.