0

Given:

git init
git commit --allow-empty -m a
git commit --allow-empty -m b
git commit --allow-empty -m c

I have:

$ git log --oneline
<c-sha1> c
<b-sha1> b
<a-sha1> a

I want:

$ git log --oneline master
<c-sha1> c
<a-sha1> a

$ git log --online slave
<?-sha1> b

I've tried:

git checkout --orphan slave
git rebase --keep-empty --onto slave <b-sha1>
Community
  • 1
  • 1
user2418306
  • 2,352
  • 1
  • 22
  • 33

1 Answers1

1

To create the slave commit, do:

git checkout <b-sha1> --orphan slave
git commit -C <b-sha1>

Then to remove the old b commit, do:

git rebase --onto <a-sha1> <b-sha1> master

Note that you can only do the second step if you have not pushed b-sha1 yet, as you should never rewrite history for pushed commits.

Also note that the contents of the snapshot of commit c will now be different, because it will not have any of the changes from commit b anymore (well technically in your example they wouldn't be, since you are doing empty commits, but if they were "real" commits they would be). If that is not what you want, then instead of doing git rebase --onto, do an interactive rebase:

git checkout master
git rebase -i <a-sha1>

Your editor will pop up with something like the following:

pick <b-sha1> Commit message for B
pick <c-sha1> Commit message for C

Copy the commit message for C, and change the contents of the file to:

 r <b-sha1> Commit message for B
 f <c-sha1> Commit message for C

Close your editor, and a new editor will pop up with the commit message for B; replace that with the commit message for C, and close the editor. Then you're done.

David Deutsch
  • 17,443
  • 4
  • 47
  • 54
  • Thank you for reply. Can you elaborate 1) why you choose `git commit -C` instead of `git cherry-pick`, 2) why in case of interactive rebase I need to use `r for B, f for C` and not `f, p` accordingly, as to eliminate B, not C? – user2418306 Feb 17 '16 at 15:49
  • 1
    @user2418306 - I used `git commit -C` because that will make the "new b" contain the same snapshot as the "old b". Doing a cherry-pick would just apply the *changes* b introduced, but applying changes to an orphan branch does not make much sense. – David Deutsch Feb 17 '16 at 16:47
  • 1
    You are correct about the interactive rebase, as long as commit A has not been pushed yet. Also, to do it your way, you will need to do `git rebase -i ^` (note the `^` symbol). – David Deutsch Feb 17 '16 at 16:49