Oleksandr Gavenko's blog
2017-04-13 00:00 Moving change from the middle of branch to top of parent branch in Git

During development in feature-branch I made change that is unrelated to feature and I want to integrate it before feature will be completed.

Suppose you have change F in the middle of development branch that you want to publish (say on master):

master          dev
  |              |
  v              v
  X -> A -> F -> B

As always in history rewriting let's assume that changes within master..dev are not published yet.

First strategy is to move F to top of dev with:

$ git co dev
$ EDITOR=emacs  git rebase -i F^1

where you should rearrange pick lines in text editor. Move first line, that represent fix because of the way we specify revisions: fix^1, to the end, save editing and exit editor. Now we should have:

master          dev
  |              |
  v              v
  X -> A -> B -> F

Create named reference to F and move dev behind F:

$ git branch fix
$ git reset --hard fix^1

Now we have:

master     dev  fix
  |         |    |
  v         v    v
  X -> A -> B -> F

Now with --onto option we can split linear history into two branches:

$ git co master
$ git rebase --onto master dev fix

After that we would have:

master fix
  |     |
  v     v   dev
  X  -> F    |
    \        v
     -> A -> B

Fast-forward master on top of fix:

$ git co master
$ git merge fix

We would have:

master fix
     | |
     v v  dev
X  -> F    |
  \        v
   -> A -> B

Get rid of temporary name fix and rebase dev on top of F:

$ git branch -d fix
$ git co dev
$ git rebase master

Alternative way is to move F to the bottom and move master pointer:

$ git co dev
$ EDITOR=emacs  git rebase -i master

After rearranging pick lines in text editor by moving F to the top F will be at the bottom of changes:

master          dev
  |              |
  v              v
  X -> F -> A -> B

Fast-forward master to F:

$ git co master
$ git merge F

What's about cherry-picking? Let's do it:

$ git co master
$ git cherry-pick F

You get:

master
     |
     v         dev
X -> F'         |
  \             v
   -> A -> F -> B

With interactive rebase remove F:

$ git co dev
$ EDITOR=emacs git rebase -i F^1

After saving edits in editor you should rebase changes on new top of master:

$ git rebase master

That's all!


Finally we can publish our fix:

$ git push origin master

I've got some tips from:

git, vcs

Feeds

all / emacs / java

Tags

adb(1), admin(1), android(1), anki(1), ansible(2), aop(1), blog(2), bytecode(1), c(1), css(2), cygwin(2), driver(1), emacs(3), fs(1), git(3), google(1), gradle(1), hardware(1), hg(2), html(1), interview(13), java(4), js(3), lang(2), lighttpd(1), markdown(1), mobile(1), naming(1), oracle(1), print(1), problem(5), python(1), quiz(6), rst(2), security(3), spring(2), sql(2), srs(1), style(1), tls(2), txt(1), unit(1), utils(1), vcs(3), web(2), win(2), windows(1)

Archive