SexyBeast SexyBeast -4 years ago 145
Git Question

Git rebase to rearrange commits involving same file

I have one file, say

foo.txt
. I add one line to it, so that it now looks like:

*existing content*
Line 1


I commit it with the message "First change". Now I open the same file again, and add another line at the end, so that it now looks like:

*existing content*
Line 1
Line 2


This I commit with the message "Second change".
git log
shows "Second change" as the topmost change, followed by "First change", as expected. Now I want to reverse the two commits, so that "First cange" comes at the top, and the "Second change" comes second from top.

I tried doing it with
git rebase -i
, I am getting consecutive merge conflicts, which I am resolving. But after that, I am left with only one commit, "Second change", the "First change" commit, which I want at the top, is now lost.

How do I do it?

Answer Source

You may need to show more of your process.

I created a small repository and a file foo.txt, added those two lines in two commits, and ran git rebase -i and swapped them:

pick f196c5b second change
pick 8d6ad6a first change

resulting in:1

1
2
3
4
5
6
existing content
<<<<<<< HEAD
||||||| parent of f196c5b... second change
Line 1
=======
Line 1
Line 2
>>>>>>> f196c5b... second change

which I now must resolve manually. What should I choose as the result? I think it is this:

1
2
3
4
5
6
existing content
Line 2

so I edit the file to have that and exit the editor, git add foo.txt, and run git rebase --continue;2 and I get another conflict, resulting in:

1
2
3
4
5
6
existing content
<<<<<<< HEAD
Line 2
||||||| parent of 8d6ad6a... first change
=======
Line 1
>>>>>>> 8d6ad6a... first change

How should I resolve this? I think the answer is to keep Line 2 from HEAD while also keeping Line 1 from 8d6ad6a... first change. It's up to me what order to put these lines into, but I think I will use:

1
2
3
4
5
6
existing content
Line 2
Line 1

so I write that to the file, exit the editor, git add foo.txt, and git rebase --continue.

That finishes the rebase and the file is now in the form it had in my last conflict-resolution.


1The ||||||| through ======= section appears because I have merge.conflictStyle set to diff3. This shows me what is in the common ancestor. It's most useful during real merges—the "merge base" of a cherry-pick is a bit suspect—but I like to keep it on at all times.

2I omit the editor sessions for writing new commit messages for the new copies of the old commits, since they are not relevant to the final result. (Remember, git rebase is copying commits. Once the rebase is done, ORIG_HEAD remembers the original, pre-rebase-copying, commits; the current branch name now finds the new, post-copy commits.)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download