Reputation: 63546
I have two commits on the same branch, one right after another. I added changes to file A to the first commit, and then I made some changes to other files and then made another commit. Now I want the changes to file A to be on the second commit rather than the first. What's the most elegant way?
Upvotes: 51
Views: 33089
Reputation: 530
I know this is an old question but I had the exact same request and I just figured out the best way to resolve this issue: you need to use interactive rebase and choose "edit" for the two commits you want to move a change from and to.
For instance, let say you have 3 commits:
$ git log -3 --oneline
97e9d62 Commit C, editing file2.txt
34b066b Commit B, creating file2.txt + editing file1.txt
73ff1bb Commit A, creating file1.txt
Now, if you want the Commit B to only contain the file2.txt creation but not the file1.txt edition which should be in Commit C, git rebase -i
will display this:
pick 73ff1bb Commit A, creating file1.txt
pick 34b066b Commit B, creating file2.txt + editing file1.txt
pick 97e9d62 Commit C, editing file2.txt
# ...
If I replace "pick" with "edit" or "e" for Commit B and Commit C and close my editor, git will stop on the second commit and let me amend my changes:
pick 73ff1bb Commit A, creating file1.txt
edit 34b066b Commit B, creating file2.txt + editing file1.txt
edit 97e9d62 Commit C, editing file2.txt
Stopped at 34b066b... Commit B, creating file2.txt + editing file1.txt
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
$ vi file1.txt # edit of file1.txt to remove the updated line
$ git commit --amend file1.txt
$ git rebase --continue
# -- git continues rebasing and stops on the Commit C to edit it
$ vi file1.txt # edit of file1.txt to put the removed line
$ git commit --amend file1.txt
$ git rebase --continue
And that's it.
Take care to save somewhere the line(s) you're removing from first commit to put them in the second one. It can be in clipboard, text file, etc. I guess it should be possible to rely on git stash
too but if it's a simple change it's easier to keep it in the clipboard.
Upvotes: 32
Reputation: 8143
Another solution to this problem
git rebase -i <commit before commits to be reordered>
(git rebase -i master
in most cases)ddp
while on the line that should move down)Upvotes: 1
Reputation: 6653
I wrote a script to meet this purpose. You can checkout out it here.
Using the script it would be as simple as:
mv-changes HEAD~ HEAD fileA
Upvotes: 27
Reputation: 5480
In the, probably unlikely, event you have just created those commits, undo the second commit with git reset HEAD^
and then add the changes to the first commit with git commit --amend
.
In the more likely event you have moved on and the commits were at some point in the past, rebasing is your best option. Without knowing your exact situation, citing a reference that explains it well is probably best.
In both the first and second event, the Pro Git book's section on rewriting history explains the options well -- both when they should be used and when caution should be used.
6.4 Git Tools - Rewriting History
Upvotes: 0
Reputation: 128829
If they're small commits, and commits should always be small in git, the simplest way is to git reset HEAD^^
and then just do them again. Note that any solution to this involves rewriting history, and if you've already pushed these commits somewhere, you shouldn't do this unless you know what you're doing.
Upvotes: 7