如何撤消成功的“git cherry-pick”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30986376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to undo a successful "git cherry-pick"?
提问by Brad Parks
On a local repo, I've just executed git cherry-pick SHA
without any conflicts or problems. I then realized I didn't want to do what I just did. I have not pushed this anywhere.
在本地存储库中,我刚刚执行时git cherry-pick SHA
没有任何冲突或问题。然后我意识到我不想做我刚刚做的事情。我没有把它推到任何地方。
How can I remove just this cherry pick?
我怎样才能去掉这个樱桃?
I'd like to know if there's a way to do this:
我想知道是否有办法做到这一点:
- when I have other local changes
- when I have no other local changes
- 当我有其他本地更改时
- 当我没有其他本地更改时
Preferably with one command for both cases if possible.
如果可能,最好对这两种情况使用一个命令。
回答by Tim
A cherry-pick is basically a commit, so if you want to undo it, you just undo the commit.
樱桃挑选基本上是一个提交,所以如果你想撤消它,你只需撤消提交。
when I have other local changes
当我有其他本地更改时
Stash your current changes so you can reapply them after resetting the commit.
存储您当前的更改,以便您可以在重置提交后重新应用它们。
$ git stash
$ git reset --hard HEAD^
$ git stash pop # or `git stash apply`, if you want to keep the changeset in the stash
when I have no other local changes
当我没有其他本地更改时
$ git reset --hard HEAD^
回答by David Deutsch
To undo your last commit, simply do git reset --hard HEAD~
.
要撤消上次提交,只需执行git reset --hard HEAD~
.
Edit: this answer applied to an earlier version of the question that did not mention preserving local changes; the accepted answer from Tim is indeed the correct one. Thanks to qwertzguy for the heads up.
编辑:此答案适用于未提及保留本地更改的问题的早期版本;蒂姆接受的答案确实是正确的。感谢 qwertzguy 的提醒。
回答by Cuadue
If possible, avoid hard resets. Hard resets are one of the very few destructive operations in git. Luckily, you can undo a cherry-pick without resets and avoid anything destructive.
如果可能,请避免硬重置。硬重置是 git 中极少数的破坏性操作之一。幸运的是,您可以在不重置的情况下撤消樱桃选择并避免任何破坏性的事情。
Note the hash of the cherry-pick you want to undo, say it is ${bad_cherrypick}
. Do a git revert ${bad_cherrypick}
. Now the contents of your working tree are as they were before your bad cherry-pick.
请注意您要撤消的cherry-pick 的哈希值,例如它是${bad_cherrypick}
. 做一个git revert ${bad_cherrypick}
。现在,您的工作树的内容与您糟糕的樱桃采摘之前一样。
Repeat your git cherry-pick ${wanted_commit}
, and when you're happy with the new cherry-pick, do a git rebase -i ${bad_cherrypick}~1
. During the rebase, delete both ${bad_cherrypick}
and its corresponding revert.
重复你的git cherry-pick ${wanted_commit}
,当你对新的樱桃挑选满意时,做一个git rebase -i ${bad_cherrypick}~1
. 在变基期间,删除两者${bad_cherrypick}
及其对应的还原。
The branch you are working on will only have the good cherry-pick. No resets needed!
你正在工作的分支只会有好的樱桃采摘。无需重置!
回答by CodeWizard
git reflog
can come to your rescue.
git reflog
可以来救你。
Type it in your console and you will get a list of your git history along with SHA-1 representing them.
在您的控制台中输入它,您将获得一个 git 历史列表以及代表它们的 SHA-1。
Simply checkout any SHA-1 that you wish to revert to
只需签出您希望恢复到的任何 SHA-1
Before answering let's add some background, explaining what is this HEAD
.
在回答之前,让我们添加一些背景知识,解释一下这是什么HEAD
。
First of all what is HEAD?
First of all what is HEAD?
HEAD
is simply a reference to the current commit (latest) on the current branch.
There can only be a single HEAD
at any given time. (excluding git worktree
)
HEAD
只是对当前分支上的当前提交(最新)的引用。在任何给定时间
只能有一个HEAD
。(不包括git worktree
)
The content of HEAD
is stored inside .git/HEAD
and it contains the 40 bytes SHA-1 of the current commit.
的内容HEAD
存储在里面.git/HEAD
,它包含当前提交的 40 字节 SHA-1。
detached HEAD
detached HEAD
If you are not on the latest commit - meaning that HEAD
is pointing to a prior commit in history its called detached HEAD
.
如果您不在最新的提交上——这意味着它HEAD
指向历史中的先前提交,它被称为detached HEAD
.
On the command line, it will look like this- SHA-1 instead of the branch name since the HEAD
is not pointing to the tip of the current branch
在命令行上,它看起来像这样 - SHA-1 而不是分支名称,因为HEAD
它没有指向当前分支的尖端
A few options on how to recover from a detached HEAD:
关于如何从分离的 HEAD 中恢复的一些选项:
git checkout
git checkout
git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back
This will checkout new branch pointing to the desired commit.
This command will checkout to a given commit.
At this point, you can create a branch and start to work from this point on.
这将签出指向所需提交的新分支。
此命令将检出给定的提交。
此时,您可以创建一个分支并从这一点开始工作。
# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>
# create a new branch forked to the given commit
git checkout -b <branch name>
git reflog
git reflog
You can always use the reflog
as well.git reflog
will display any change which updated the HEAD
and checking out the desired reflog entry will set the HEAD
back to this commit.
您也可以随时使用reflog
。git reflog
将显示更新HEAD
并检出所需的引用日志条目的任何更改将设置HEAD
回此提交。
Every time the HEAD is modified there will be a new entry in the reflog
每次修改 HEAD 时都会有一个新条目 reflog
git reflog
git checkout HEAD@{...}
This will get you back to your desired commit
这会让你回到你想要的提交
git reset --hard <commit_id>
git reset --hard <commit_id>
"Move" your HEAD back to the desired commit.
“移动”你的 HEAD 回到所需的提交。
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
- Note: (Since Git 2.7)
you can also use thegit rebase --no-autostash
as well.
- 注意:(从 Git 2.7 开始)
您也可以使用git rebase --no-autostash
。
git revert <sha-1>
git revert <sha-1>
"Undo" the given commit or commit range.
The reset command will "undo" any changes made in the given commit.
A new commit with the undo patch will be committed while the original commit will remain in the history as well.
“撤消”给定的提交或提交范围。
reset 命令将“撤消”在给定提交中所做的任何更改。
带有撤消补丁的新提交将被提交,而原始提交也将保留在历史记录中。
# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>
This schema illustrates which command does what.
As you can see there reset && checkout
modify the HEAD
.
这个模式说明了哪个命令做什么。
如您所见,reset && checkout
修改HEAD
.
回答by brogrammer
Faced with this same problem, I discovered if you have committed and/or pushed to remote since your successful cherry-pick, and you want to remove it, you can find the cherry-pick's SHA by running:
面对同样的问题,我发现如果您在成功挑选樱桃后已经提交和/或推送到远程,并且您想删除它,您可以通过运行找到樱桃挑选的 SHA:
git log --graph --decorate --oneline
git log --graph --decorate --oneline
Then, (after using :wq
to exit the log) you can remove the cherry-pick using
然后,(使用:wq
退出日志后)您可以使用删除樱桃挑选
git rebase -p --onto YOUR_SHA_HERE^ YOUR_SHA_HERE
git rebase -p --onto YOUR_SHA_HERE^ YOUR_SHA_HERE
where YOUR_SHA_HERE
equals the cherry-picked commit's 40- or abbreviated 7-character SHA.
其中YOUR_SHA_HERE
等于精心挑选的提交的 40 个或缩写的 7 个字符的 SHA。
At first, you won't be able to push your changes because your remote repo and your local repo will have different commit histories. You can force your local commits to replace what's on your remote by using
起初,您将无法推送更改,因为您的远程仓库和本地仓库将具有不同的提交历史。您可以使用以下命令强制本地提交替换遥控器上的内容
git push --force origin YOUR_REPO_NAME
git push --force origin YOUR_REPO_NAME
(I adapted this solution from Seth Robertson: See "Removing an entire commit.")
(我改编了Seth Robertson 的这个解决方案:请参阅“删除整个提交”。)
回答by qwertzguy
One command and does notuse the destructive git reset
command:
只需一个命令,就不能使用破坏性的git reset
命令:
GIT_SEQUENCE_EDITOR="sed -i 's/pick/d/'" git rebase -i HEAD~ --autostash
GIT_SEQUENCE_EDITOR="sed -i 's/pick/d/'" git rebase -i HEAD~ --autostash
It simply drops the commit, putting you back exactly in the state before the cherry-pick even if you had local changes.
它只是删除提交,即使您有本地更改,也可以让您完全回到挑选之前的状态。