I had a feature branch and a master branch. I did some work on the feature, merged into master, pushed the changes, and then deleted the feature branch, both remotely and locally. So far, so good.
After merging, I realized there was a problem with my feature changes. I'd like to undo the merge on master, but still keep the feature changes so I can work on them again. How can I do this?
What I had originally:
A---B---C---D [master]
\
E----F [feature]
What I have now:
A---B---C---D---EF (squashed) [master]
What I want:
A---B---C---D [master]
\
EF [feature]
How do I accomplish this?
There are many command sequences that can do it. Here is one short one.
git status
), so that step 3 can't wreck anything. This is always a useful base step. :-) git branch feature
.git reset --hard HEAD^
or git reset --hard HEAD~
(either spelling is fine, use whatever you prefer to type in).Explanation:
Step 1 should be obvious.
Step 2 creates the new name feature
, identifying the same squashed EF
commit that master
identifies. This gives you:
A--B--C--D--EF <-- master (HEAD), feature
The (HEAD)
annotation shows which branch name is the current branch name, and therefore which commit is the current commit as well (in this case EF
).
Step 3 moves the current branch name to point to the selected commit. The current branch name is, as we see in the diagram, master
. The selected commit is one first-parent hop back from commit EF
: EF^
means "first parent of commit EF
" and EF~
means "starting from EF
, step back one first parent".
The result is:
A--B--C--D <-- master (HEAD) \\ EF <-- feature
which is what you wanted.
Note that EF~2
would start at EF
and count back twice, to D
then to C
, so that master
(still HEAD
) would point to commit C
instead of commit D
. The --hard
to git reset
tells Git to replace the index content with that from the chosen commit, and to update your work-tree to match.
You need to reset --sort master branch to the commit before merge D
this will make you master head on D
commit and the EF
commit will be local on your machine, make sure from this then force push the master to remove unneeded EF
commit then create new feature
branch and commit the local changes to it again
Steps:
git reset --soft YOUR_COMMIT_HASH
git status
// to make sure that your files not gone
git stash
// to make your is head clean
git push -f origin master
git checkout -b feature
git stash pop
// to retrieve the removed commit changes
reference: https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---soft
This could be accomplished in 3 steps with:
On master
branch:
$ git reset --hard <Hash of D> # D is now the tip of master branch
$ git switch -c feature # Creates a new feature branch based on D and move to it
Now on the newly created feature
branch:
$ git cherry-pick <Hash of EF> # Restores the EF commit
This is all that is required.
When a branch is deleted, any lost commits can be found in the reflog
for a given period of time ( 30 days by default ), so the EF
commit hash could be found there just in case:
$ git reflog
Note: The switch -c
command is available from git 2.23.0+
and does the same as checkout -b
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.