在 Git 中丢弃本地提交

Posted

技术标签:

【中文标题】在 Git 中丢弃本地提交【英文标题】:Throw away local commits in Git 【发布时间】:2011-07-03 02:50:33 【问题描述】:

由于一些糟糕的挑选,我的本地 Git 存储库目前比原点提前 5 次提交,并且状态不佳。我想摆脱所有这些提交并重新开始。

显然,删除我的工作目录并重新克隆就可以了,但是再次从 GitHub 下载所有内容似乎有点过头了,而且没有充分利用我的时间。

也许git revert 是我需要的,但我不想在原点(甚至六个)之前完成 10 次提交,即使它确实将代码本身恢复到正确的状态。我只是想假装最后半小时从未发生过。

有没有一个简单的命令可以做到这一点?这似乎是一个明显的用例,但我没有找到任何示例。


请注意,这个问题是专门关于commits的,不是关于:

未跟踪的文件 未分阶段的更改 已分阶段但未提交的更改

【问题讨论】:

Various ways to remove local Git changes的可能重复 【参考方案1】:

如果您的多余提交只对您可见,您可以这样做 git reset --hard origin/<branch_name> 回到原点。这会将存储库的状态重置为上一次提交,并且会丢弃所有本地更改。

执行git revert 会使 new 提交删除 old 提交,从而使每个人的历史保持正常。

【讨论】:

git reset --hard <commit hash, branch, or tag> 如果您想转到远程分支以外的特定参考。 明确一点,如果你不在master 上工作,而是在另一个分支上工作,你应该运行git reset --hard origin/<your-branch-name> 这不仅会丢弃本地提交,还会丢弃工作树中的所有内容(即本地文件)。如果您只想取消提交,但保持您的工作不变,您应该按照***.com/questions/2845731/… 执行“git reset HEAD^”... 您可能希望在此之后进行 Fetch。这修复了 SourceTree 上等待推送的提交数计数器。 git reset --hard origin/<branch_name> 它也会重置项目配置,所以请注意这一点。我有一个很大的.cfg 文件,它被重置为默认值。我不得不再次花费数小时。【参考方案2】:

只需删除您的本地 master 分支并像这样重新创建它:

git branch -D master
git checkout origin/master -b master

【讨论】:

当回溯您的更改会花费太多时间时,这很有效,这在我身上发生了几次变基后。 对团队成员之间的子树拉/推问题很有用! 当你想恢复一个分支而不是只恢复一个分支时,这是完美的。 这不是删除单个本地提交的好方法。最好使用git reset --hard origin/<branch_name> 也许该解决方案会起作用,但这并不意味着它是正确的。【参考方案3】:

删除最近的提交,而不破坏您所做的工作:

git reset --soft HEAD~1

删除最近的提交并移除更改:

git reset --hard HEAD~1

【讨论】:

有用的答案。谢谢!我使用了 git reset --soft origin/master @TarunKumar 谢谢!我正在使用 VS 集成,而您的解决方案是我能够在我无权签入的分支中清除一堆我不想要的合并提交的唯一方法。 谢谢,正是我正在寻找的,“git reset --soft HEAD~1”完成了我无意中提交的工作并想要恢复但有其他我不想成为的文件恢复后销毁。 在 Windows --hard "HEAD@1" 在上面的答案中首先给出 --soft 答案可能会帮助一些过分热心的 StackExchange 撇油器......没有任何损失,没有获得任何知识【参考方案4】:

试试:

git reset --hard <the sha1 hash>

让你的头脑重新回到你想去的地方。使用 gitk 查看您想要进行的提交。您也可以在 gitk 中进行重置。

【讨论】:

赞成这个 b/c 这是有用的信息,但 Ben Jackson 的回答得到了准确解决我想要的问题的复选标记——以一种不需要我查找提交哈希的方式。 :) 这是你的新分支还没有被推送到原点的那个【参考方案5】:

在您的分支尝试中:

git reset --hard origin/<branch_name>

验证反转(到状态,没有本地提交),因此使用“git log”或“git status”。

【讨论】:

@Troyseph :上面列出的所有答案,我都按原样进行了尝试,但没有解决问题。上述任何答案中均未说明的通用方法是此处尝试回答的方法。 接受的答案与您的相同,减去通用分支名称,并且在 cmets @Zoltan 中明确表示 Just to be clear, if you're not working on master but on another branch, you should run git reset --hard origin/&lt;your-branch-name&gt; 这是我认为最好的答案。 是的。就是这个!【参考方案6】:

如果您使用的是 Atlassian SourceTree 应用程序,您可以使用上下文菜单中的重置选项。

【讨论】:

【参考方案7】:

简单的解决方案是将本地 master 分支 HEAD 匹配到 origin/master 分支 HEAD

git reset --hard origin/master

PS: origin/master - 是指向 master 分支的远程指针。 您可以将 master 替换为任何分支名称

【讨论】:

【参考方案8】:

git reset --hard @u* 删除当前分支上的所有本地更改,包括提交。我很惊讶没有人发布此内容,但考虑到您不必查找要恢复或使用分支的提交。

* 即重置到@upstream 处的当前分支——通常是origin/&lt;branchname&gt;,但并非总是如此

【讨论】:

一些像fish这样的shell会解释“@”,所以你可能必须把'@u'放在引号中,例如`git reset --hard '@u'。无论如何,很好的发现! 真棒答案真棒 如何打印@u的值?【参考方案9】:

在回答之前,让我们添加一些背景知识,解释一下HEAD 是什么。因为下面的一些选项会导致头部分离

First of all what is HEAD?

HEAD 只是对当前分支上当前提交(最新)的引用。 在任何给定时间只能有一个HEAD。 (不包括git worktree

HEAD 的内容存储在.git/HEAD 中,其中包含当前提交的 40 字节 SHA-1。


detached HEAD

如果您不是最新的提交 - 这意味着 HEAD 指向历史上的先前提交,它称为 detached HEAD

在命令行上,它看起来像这样 - SHA-1 而不是分支名称,因为 HEAD 没有指向当前分支的尖端

关于如何从分离的 HEAD 中恢复的几个选项:


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

这将签出指向所需提交的新分支。 此命令将签出给定的提交。 此时,您可以创建一个分支,并从这一点开始工作。

# 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

您也可以随时使用refloggit reflog 将显示更新HEAD 的任何更改,并且检查所需的引用日志条目会将HEAD 设置回此提交。

每次修改 HEAD 时,reflog 中都会有一个新条目

git reflog
git checkout HEAD@...

这会让你回到你想要的提交


git reset --hard &lt;commit_id&gt;

“移动”你的 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.
注意:(Since Git 2.7) 您也可以使用git rebase --no-autostash

git revert &lt;sha-1&gt;

“撤消”给定的提交或提交范围。 重置命令将“撤消”在给定提交中所做的任何更改。 将提交带有撤消补丁的新提交,而原始提交也将保留在历史记录中。

# 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>

此架构说明了哪个命令执行什么操作。 如您所见,reset &amp;&amp; checkout 修改 HEAD

【讨论】:

【参考方案10】:

使用任意次数,在不删除您最近创建的任何文件的情况下恢复到上次提交。

git reset --soft HEAD~1

然后使用

git reset HEAD <name-of-file/files*>

取消暂存或取消跟踪。

【讨论】:

【参考方案11】:

要查看/获取您也想返回的提交的 SHA-1 id

gitk --all

回滚到那个提交

git reset --hard sha1_id

!注意。在该提交之后所做的所有提交都将被删除(以及您对项目的所有修改)。所以首先最好将项目克隆到另一个分支或复制到另一个目录。

【讨论】:

这对于远程不再可用的情况非常有用,并且只需要重置为一些本地提交。 gitk 很棒 - 事先没有意识到这一点。 如果您已经在 gitk 中,您也可以简单地右键单击提交并选择“将分支 XY 重置到此处”。 并且较新的提交不会立即被删除。不再有指向它们的分支(请记住,分支只不过是特定提交的“书签”)。【参考方案12】:

我有一种情况,我想删除一个未推送的提交,但该提交在另一个提交之前。为此,我使用了以下命令

git rebase -i HEAD~2 -> 它将变基最后两次提交

我使用 'drop' 作为我想要删除的提交签名。

【讨论】:

【参考方案13】:

删除未跟踪的文件(未提交的本地更改)

git clean -df

永久删除所有本地提交并获取最新的远程提交

git reset --hard origin/<branch_name>

【讨论】:

【参考方案14】:

如果 您的分支领先于 'origin/XXX' 5 次提交。

您可以发出:

git reset --hard HEAD~5

它应该删除最后 5 个提交。

【讨论】:

【参考方案15】:

对于未推送的本地提交,您还可以使用git rebase -i 删除或压缩提交。

【讨论】:

我知道这可能不是最短的解决方案,但我赞成你,因为恕我直言git rebase -i 是解决许多类似问题的更通用的方法,并且在各种情况下都有帮助。 在删除所有提交时使用 drop 关键字(而不是删除一行)以避免 rebase 中止。【参考方案16】:

对于那些对 Visual Studio 解决方案感兴趣的人,这里是练习:

    Team Explorer 窗口中,连接到目标存储库。 然后从Branches,右键单击感兴趣的分支并选择View history。 右键单击History 窗口中的提交并选择Reset -&gt; Delete changes (--hard)

这将丢弃您的本地提交并将您的存储库状态重置为选定的提交。 IE。您在提取 repo 后所做的更改将会丢失。

【讨论】:

【参考方案17】:

如果您只是想丢弃本地提交并将修改保留在文件中,那么请执行git reset @~ 其他答案解决了硬重置

【讨论】:

【参考方案18】:

找到要恢复到的提交的 sha1:

za$ git reflog
... snip ...
cf42fa2... HEAD@0: commit: fixed misc bugs
~
~
cf42fa2... HEAD@84: commit: fixed params for .....
73b9363... HEAD@85: commit: Don't symlink to themes on deployment.
547cc1b... HEAD@86: commit: Deploy to effectif.com web server.
1dc3298... HEAD@87: commit: Updated the theme.
18c3f51... HEAD@88: commit: Verify with Google webmaster tools.
26fbb9c... HEAD@89: checkout: moving to effectif

然后使用 --mixed 标志,以便您“重置 HEAD 和索引”:

za$ git reset --mixed cf42fa2

可用标志:

za$ git reset -h

-q, --quiet           be quiet, only report errors
--mixed               reset HEAD and index
--soft                reset only HEAD
--hard                reset HEAD, index and working tree
--merge               reset HEAD, index and working tree
--keep                reset HEAD but keep local changes
--recurse-submodules[=<reset>]
                      control recursive updating of submodules
-p, --patch           select hunks interactively
-N, --intent-to-add

【讨论】:

【参考方案19】:

你可以使用这个 git 命令

git reset --hard origin/<branch_name>

【讨论】:

【参考方案20】:
git reset --hard <SHA-Code>

如果您在本地副本上犯了一些错误,您想确保不会被错误地推送到远程分支,这将派上用场。

可以通过查看 git 仪表板的 webVersion 来获取分支上最后一次提交的 SHA-Code。

通过这种方式,您可以与分支上的最后一次提交同步。

您可以在成功完成硬重置后执行git pull 以确认 syn 没有任何新内容,即您可以看到该消息。

您的分支是最新的Origin/&lt;Branch Name&gt;

【讨论】:

【参考方案21】:

如果你的本地仓库一团糟,那么在 Git 中丢弃本地提交的可靠方法是...

    使用“git config --get remote.origin.url”获取远程源的URL 将本地 git 文件夹重命名为“my_broken_local_repo” 使用“git clone ”获取远程 git 存储库的新本地副本

根据我的经验,Eclipse 可以很好地处理周围发生的变化。但是,您可能需要在 Eclipse 中选择受影响的项目并清理它们以强制 Eclipse 重新构建它们。我猜其他 IDE 可能也需要强制重建。

上述过程的另一个好处是,您会发现您的项目是否依赖于未放入 git 的本地文件。如果您发现缺少文件,则可以从“my_broken_local_repo”复制它们并将它们添加到 git。一旦您确信您的新本地仓库拥有您需要的一切,您就可以删除“my_broken_local_repo”。

【讨论】:

以上是关于在 Git 中丢弃本地提交的主要内容,如果未能解决你的问题,请参考以下文章

git 丢弃本地所有文件(新增、删除、修改)

常用git命令

git如何放弃所有本地修改

source tree 使用心得

Git重置(撤消、丢弃)文件变更

(转)Git操作