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.
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.
You can use git cherry-pick <commit> from the target branch to copy the commit there (<commit> can be the branch name if it's the last commit).
You can use git reset --hard HEAD^ to erase the last commit from the original branch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With