Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

git - Move commit to different branch

I'm wondering if there is a simple way to move commit from branch A to branch B.

I was working on "develop" branch, then created a new one, let's say "featureA" to start developing new feature. I made 2 commits, but first one should have gone to "develop" instead of "featureA" because it was just a small fix, but I forgot to change branch, so can I simply move commit 1 to branch "develop" and remove it from "featureA"?

Changes are still not pushed, just local.

I will appreciate any help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In this particular case it is easy. To see why, draw (part of) the commit graph.

You started with something like this:

...--o--*   <-- develop (HEAD), origin/develop

You then created a new branch name, feature, pointing to the same tip-of-develop commit *. You attached your HEAD to the new branch, giving:

...--o--*   <-- develop, feature (HEAD), origin/develop

Now you made two new commits. Let's call them A and B rather than using their real hash IDs, which are big and ugly and forgettable. Commit A has, as its parent, commit *, and commit B has commit A as its parent, and the name feature now points to commit *:

...--o--*   <-- develop, origin/develop
         
          A--B   <-- feature (HEAD)

Leaving feature alone, let's tell Git to move the name develop to point to commit A, the minor fix you want to have on your develop:

...--o--*   <-- origin/develop
         
          A   <-- develop
           
            B   <-- feature

I've removed the attached HEAD temporarily since there are several ways to adjust develop like this and HEAD may re-attach as we do them. This is the final picture you want: no commits have changed at all, but your local name develop now points to the first commit, while feature points to the second one.

So: how shall we do it?

One quite-safe method (can't lose any work) is to git checkout develop first, then use git merge --ff-only to fast-forward develop to the correct commit. That's commit A, which is one step back from feature, so we can do this:

git checkout develop
git merge --ff-only feature~1

This will leave you with develop pointing to commit A (and your HEAD attached to develop, so you have to git checkout feature to keep going).

Another way is to check out develop and use git reset --hard to move the label develop to any arbitrary commit (while also updating your index / staging-area and your work-tree). This is essentially the same as above, but it lets you move the name anywhere, even if that's not a sensible move, so the above is probably preferable.

Yet another way is to use git branch -f to force move the name to the location you want:

git branch -f develop feature~1

This leaves your HEAD attached to feature, so that you don't have to git checkout feature to keep working. However, like the git reset method, it's not very safe as it lets you move the name to any commit, even if that makes no sense.

Finally, there's a very sneaky way to update develop in a fast-forward fashion (a la git merge --ff-only) without checking out develop—in fact you need to stay on some other branch to do it:

git push . feature~1:develop

This has your Git call up your own Git, and propose to itself that it should move the name develop to point to the commit whose hash ID was obtained by parsing feature~1. Your Git will obey your Git if and only if this is a fast-forward, since there is no force flag here.

Use whichever of these you like; they all achieve the same result in the end, except for where your HEAD is attached.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...