ChatGPT解决这个技术问题 Extra ChatGPT

在 Git 中丢弃本地提交

git

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

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

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

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

请注意,这个问题专门关于提交,而不是关于:

未跟踪的文件

未分阶段的变化

分阶段但未提交的更改


Y
Yash

如果您的多余提交仅对您可见,您只需执行 git reset --hard origin/<branch_name> 即可移回原点所在的位置。这会将存储库的状态重置为先前的提交,并将丢弃所有本地更改。

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


git reset --hard <commit hash, branch, or tag> 如果您想转到远程分支以外的特定参考。
这不仅会丢弃本地提交,还会丢弃工作树中的所有内容(即本地文件)。如果您只想取消提交,但保持您的工作不变,您应该按照 stackoverflow.com/questions/2845731/… 执行“git reset HEAD^”...
您可能想在此之后进行 Fetch。这修复了 SourceTree 上等待推送的提交数计数器。
git reset --hard origin/<branch_name> 它也会重置项目配置,因此请注意这一点。我有一个很大的 .cfg 文件,它被重置为默认值。我不得不再次花费数小时。
请更新您的答案以包括这实际上会删除您所做的所有工作(例如 2016 年提到的@aaronbauman)。当我只想撤消上一次提交而不使用 revert 时,我失去了很多工作,这样我就可以在推送之前取出一个敏感值。
J
James L.

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

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 撇油器......没有丢失,没有获得任何知识
R
Ramon Zarazua B.

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

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

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

尝试:

git reset --hard <the sha1 hash>

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


赞成这个 b/c 这是有用的信息,但是 Ben Jackson 的回答得到了准确解决我想要的问题的复选标记——以一种不需要我查找提交哈希的方式。 :)
这是您的新分支尚未被推送到原点的情况
p
parasrish

在您的分支尝试中:

git reset --hard origin/<branch_name>

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


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

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

https://i.stack.imgur.com/2fbjm.jpg


n
narwanimonish

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

git reset --hard origin/master

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


D
David Moles

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

* 即重置到 @{upstream} 处的当前分支——通常是 origin/<branchname>,但不总是


像fish 这样的shell 会解释“@”,因此您可能必须将'@{u}' 放在引号中,例如`git reset --hard '@{u}'。总之,很好找!
很棒的答案很棒
你如何打印@{u} 的值?
C
CodeWizard

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

首先什么是HEAD?

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

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

分离头

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

https://i.stack.imgur.com/OlavO.png

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

https://i.stack.imgur.com/qplvo.png

关于如何从分离的 HEAD 中恢复的一些选项:

git结帐

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

您也可以始终使用 reflog
git reflog 将显示更新 HEAD 的任何更改,并且检查所需的 reflog 条目会将 HEAD 设置回此提交。

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

git reflog
git checkout HEAD@{...}

这将使您回到所需的提交

https://i.stack.imgur.com/atW9w.png

git reset --hard

将您的 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.

注意:(从 Git 2.7 开始)您也可以使用 git rebase --no-autostash。

git revert

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

# 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 && checkout 修改 HEAD

https://i.stack.imgur.com/NuThL.png


L
Lahcen

你可以使用这个 git 命令

git reset --hard origin/<branch_name>

正是我想要的。我省略了“/”,因为我要重置的分支是我当前的分支。
J
Jimut123

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

git reset --soft HEAD~1

然后使用

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

取消舞台或取消跟踪。


P
Peter Mortensen

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

git rebase -i HEAD~2 ->它将重新设置最后两个提交

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


P
Peter Mortensen

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

gitk --all

回滚到那个提交

git reset --hard sha1_id

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


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

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

git clean -df

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

git reset --hard origin/<branch_name>

s
shizhen

如果您的分支在 'origin/XXX' 之前 5 次提交。

您可以发出:

git reset --hard HEAD~5

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


N
Nikhil Katre

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


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

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

在 Team Explorer 窗口中,连接到目标存储库。然后从分支中,右键单击感兴趣的分支并选择查看历史记录。右键单击历史记录窗口中的提交,然后选择重置 -> 删除更改 (--hard)。

这将丢弃您的本地提交并将您的回购状态重置为选定的提交。即,您提取回购后的更改将丢失。

更新

上述程序在 VS2019 之前运行良好;在 VS2022 中有新的 Git 体验。工作流程类似,但 UI 有点不同。使用 Git 菜单中的 Manage Branches 代替 Team Explorer。现在只需单击左侧的分支,其历史记录就会显示在右侧。然后去Right Click -> Reset -> Delete Changes (--hard)


A
Ashish Banker

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


z
z atef

找到要恢复到的提交的 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

S
Samuel Philipp
git reset --hard <SHA-Code>

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

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

这样您就可以与分支上的最后一次提交同步。

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

您的分支是最新的 Origin/<Branch Name>


A
Adam Gawne-Cain

如果您将本地存储库弄得一团糟,那么在 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”。


O
Olivier Elonga

对于所有未暂存的更改git checkout -- .

对于特定文件 git checkout -- path/to/file/to/revert


J
JohnTang

更新:

您可以在此处使用新的 GIT LFS:https://git-lfs.github.com/

git lfs migrate import --include="*.file_type"

然后 git 推送


A
ActualAl

您可以查看使用带有 drop 命令的交互式变基

所以说最后三个提交......

git rebase -i HEAD~3

交换选择命令

pick <hash1> Commit message 1
pick <hash2> Commit message 2
pick <hash3> Commit message 3

对于删除命令

drop <hash1> Commit message 1
drop <hash2> Commit message 2
drop <hash3> Commit message 3