2

Suppose I have the following history:

A ─▶ B  -- master
      ╲
       ◀
        C ─▶ D ─▶ E  -- feature

At point E, I stuble upon a small bug in the code that has strictly speaking nothing to do with feature, but happens to be important at this point, though it previously went unnoticed. I'll then first of all fix it right in place:

A ─▶ B  -- master
      ╲
       ◀
        C ─▶ D ─▶ E ─▶ F  -- feature
                       ⋮
                       fix bug

But, since it is after all a bug that has not much to do with feature as such, this isn't really the history I want – this fix should be right in master (if not in a dedicated bugfix branch).

git checkout master
git cherry-pick F

A ─▶ B ─▶ F'  -- master
      ╲
       ◀
        C ─▶ D ─▶ E ─▶ F  -- feature

Ok, fine, but I can't really leave it at this (or can I?) – F now occurs two times in active branches that I yet want to merge. I could

git checkout feature
git reset --hard HEAD^

A ─▶ B ─▶ F'  -- master
      ╲
       ◀
        C ─▶ D ─▶ E  -- feature

and wait for F' when merging feature back into master, but that won't do because I don't have the bugfix available right where I need it – for the work on feature. So I'll then finish it off with

git rebase master

A ─▶ B ─▶ F'  -- master
           ╲
            ◀
             C' ─▶ D' ─▶ E'  -- feature

This feels a complicated and somewhat error-prone way of achieving the goal, which is essentially just moving a single commit up in the history.

Is there a more straghtforward way to accomplish this task?

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • 2
    You can skip then reset part when doing it that way - rebasing will notice that the F commit is already present and skips it. Other than that, I see no other way to do this. – 1615903 Sep 22 '16 at 11:37
  • ^- agreed, reset is unnecessary because git is smart enough to drop the duplicate commit after rebase. Nice arrows btw – Jeff Puckett Sep 22 '16 at 11:43

2 Answers2

1

You may be interesting by gitl project under github which provide git cherry-copy and git cherry-move commands. This is not possible to do it faster using git core commands.

Original answer from lennartcl on this other post.

Community
  • 1
  • 1
Flows
  • 3,675
  • 3
  • 28
  • 52
1

Summary

In my opinion the easiest way would be to fix the bug directly on master (or in a bugfix branch based on master). After master includes the bugfix you can rebase your feature branch onto master. Done.

Detailed flow (with bugfix branch)

Bugfix branch:

git checkout master && git checkout -b bugfix

* 98f2c4f (HEAD -> bugfix) bugfix commit
| * efe77fd (feature1) test2
|/
* 3c3a2ee (master) test

Merge bugfix into master and delete bugfix:

git checkout master && git merge bugfix && git branch -d bugfix

* 98f2c4f (HEAD -> master) bugfix commit
| * efe77fd (feature1) test2
|/
* 3c3a2ee test

Rebase feature branch onto master:

git checkout feature1 && git rebase master

* e3a55ed (HEAD -> feature1) test2
* 98f2c4f (master) bugfix commit
* 3c3a2ee test
gucce
  • 597
  • 4
  • 12
  • You're probably right. However, it is rather convenient to first fix the bug on `feature`, because right there I actually have a failing test to work against. Is there a good way to transfer that work to `master` _without_ ever committing it on `feature`? – leftaroundabout Sep 26 '16 at 11:26
  • The easiest way to transport uncommitted changes from one branch to another is to use `git stash` on the one you are currently on and then `git stash pop` on the target branch. But beware that `git stash` stashes all of your local modifications, so you would have to make sure those only concern your bug. – gucce Sep 28 '16 at 15:05