1

i.e. how do I go from


master : A-B-C-D-E-F-G

to

master: A-B-E-F-G
           \
feature:    C-D 

Obviously its now clear that CD should have been in a feature branch, as that change is now delayed.

This is a subtly different issue to the others I've seen here and and here

Community
  • 1
  • 1
Andiih
  • 12,285
  • 10
  • 57
  • 88
  • That's (currently) three viable answers. Any advantages to each? I quite like @larsmans cherry pick solution as not requiring rebasing – Andiih Oct 25 '13 at 14:31
  • But it does require rebasing... – pattivacek Oct 25 '13 at 14:33
  • ah yes. Its does doesn't it. Slaps self on head. So which do I try 1st??? Or are they all equivalents? – Andiih Oct 25 '13 at 14:41
  • Now that I have reviewed what `--onto` does, I have to admit, I think R0MANARMY's answer is actually just barely superior, despite that mine has more votes. The only real difference is that my version (using `-i` for interactive rebase) requires you to manually select commits C an D for removal, whereas the `--onto` version does that automatically in one command line. As to the third answer that was deleted, it was fine but more long-winded. (Although I liked the backup idea it mentioned, which I have used myself before.) – pattivacek Oct 25 '13 at 15:04

2 Answers2

3

Starting at the HEAD (G) of master:

git branch feature D  # Create new branch at D.
git rebase -i B       # Use interactive rebase to remove C D from master.
pattivacek
  • 5,617
  • 5
  • 48
  • 62
2

This answer assumes you either haven't pushed master or you're the only person working on the project (in which case it doesn't really matter). If you have pushed master and someone else pulled your changes, you'll need to communicate with them to make sure they update their repositories appropriately.

                                  # Assuming you're on master
git branch <feature> <D>          # Create a branch named <feature> at commit <D>
git rebase --onto <B> <D> master  # Transplant branch

Git rebase documentation has a pretty good graphical explanation of what rebase --onto does.


If you want to avoid a rebase altogether, you should be able to do

git branch <feature> <D>          # Create a branch named <feature> at commit <D>
git revert <D>                    # undo D
git revert <C>                    # undo C

This will result in a history like this

A-B-C-D-E-F-G-!D-!C
      ^           ^
   feature      master

Anyone who checks out master, will see code as if commits C and D never happened, you'll just have a couple of reverts in your history. That's the preferred way of backing changes out of a branch that has been pushed.

Roman
  • 19,581
  • 6
  • 68
  • 84
  • going with the revert version - the branch has been pushed, so not rewriting history is a major+. – Andiih Oct 28 '13 at 09:16
  • The revert part of the answer was just a lucky guess at what you were looking for. You should include that you're looking for an answer not involving a `rebase` in the question. – Roman Oct 28 '13 at 11:25
  • I didn't fully grok its significance until you'd pointed out the dangers if I had pushed master: by which time you'd already answered :-) Thx! – Andiih Oct 28 '13 at 14:05