ChatGPT解决这个技术问题 Extra ChatGPT

我可以删除 git commit 但保留更改吗?

在我的一个开发分支中,我对我的代码库进行了一些更改。在我能够完成我正在开发的功能之前,我必须将我当前的分支切换到 master 来演示一些功能。但是仅使用“git checkout master”就保留了我在开发分支中所做的更改,从而破坏了 master 中的一些功能。所以我所做的是在我的开发分支上提交更改,并使用提交消息“临时提交”,然后为演示签出 master。

现在我已经完成了演示并回到我的开发分支上工作,我想删除我所做的“临时提交”,同时仍然保留我所做的更改。那可能吗?

下次:git stash
@MattBall,不一定。虽然 git stash 是一个很好的工具,但“正在进行的工作”一次性提交也是一种相当合法的设备。
这是来自 Github 的绝佳资源:How to undo (almost) anything with Git
@MattBall @kostix 是的,存储特别不适合“长期”存储,因为它是整个回购的一个全局堆栈。我希望能够将更改存储在一个分支上,然后转到其他分支,做其他任何事情,几天后回来,而不必担心我可能在过渡期间在其他分支上使用了 git stash
关于 stash 值得注意的一点是它完全是本地的,并且很容易因 repo 删除或重新创建或硬件故障或丢失而导致代码丢失。 IMO,它真的应该只用于非常短期的 WIP。在去度假之前喜欢 WIP 提交:P .. 称之为大脑转储提交!

S
Svish

就这么简单:

git reset HEAD^

注意:某些 shell 将 ^ 视为特殊字符(例如某些 Windows shell 或 ZSH with globbing enabled),因此在这些情况下您可能必须引用 "HEAD^" 或使用 HEAD~1

没有 --hard--softgit reset 移动您的 HEAD 以指向指定的提交,而不更改任何文件。 HEAD^ 指的是您当前提交的(第一个)父提交,在您的情况下是临时提交之前的提交。

请注意,另一个选项是照常进行,然后在下一个提交点运行:

git commit --amend [-m … etc]

它将改为编辑最近的提交,具有与上述相同的效果。

请注意,如果您已经将错误的提交推送到其他人可能已将其拉出的地方,这(与几乎所有 git 答案一样)可能会导致问题。尽量避免这种情况


这是迄今为止最简单的,但是如果您已经将您的提交推送到遥控器并且其他人拉了它,那么除了道歉之外,我会非常犹豫是否要做任何事情。
这样做后我得到More?。无论我在那个提示符下输入什么,都会给我 fatal: ambiguous argument 'HEADwhateverItypedIn': unknown revision or path not in the working tree.
@DaAwesomeP 听起来您正在使用将 ^ 视为特殊字符的外壳。您可以引用参考 "HEAD^",或使用替代语法 HEAD~1 unquoted
为我工作,尽管git reset HEAD\^不得不转义字符
@kostix FWIW 该链接已更改为 git-scm.com/book/en/v2/Git-Tools-Reset-Demystified
S
Steven

有两种处理方法。哪个更容易取决于您的情况

重置

如果您要删除的提交是最后一次提交,并且您还没有做任何额外的工作,您可以简单地使用 git-reset

git reset HEAD^

将您的分支带回当前 HEAD 之前的提交。但是,它实际上并没有更改工作树中的文件。结果,该提交中的更改显示为已修改-就像“取消提交”命令。事实上,我有一个别名可以做到这一点。

git config --global alias.uncommit 'reset HEAD^'

然后,您以后可以只使用 git uncommit 来备份一个提交。

挤压

压缩提交意味着将两个或多个提交合并为一个。我经常这样做。在您的情况下,您提交了一半完成的功能,然后您将完成它并使用正确的永久提交消息再次提交。

git rebase -i <ref>

我在上面说是因为我想明确表示这可能是任意数量的提交。运行 git log 并找到您要删除的提交,复制其 SHA1 并使用它来代替 <ref>。 Git 将带您进入交互式变基模式。它将显示您当前状态与您放置 <ref> 的任何内容之间的所有提交。因此,如果 <ref> 是 10 次提交之前,它将显示所有 10 次提交。

在每次提交之前,都会有 pick 字样。找到您要删除的提交并将其从 pick 更改为 fixupsquash。使用 fixup 只需丢弃提交消息并将更改合并到列表中的直接前任中。 squash 关键字做同样的事情,但允许您编辑新组合提交的提交消息。

请注意,当您退出编辑器时,提交将按照它们在列表中显示的顺序重新提交。因此,如果您进行了临时提交,然后在同一分支上进行了其他工作,并在以后的提交中完成了该功能,那么使用 rebase 将允许您重新排序提交并压缩它们。

警告:

变基会修改历史记录 - 不要对您已经与其他开发人员共享的任何提交执行此操作。

藏匿

将来,为避免此问题,请考虑使用 git stash 临时存储未提交的工作。

git stash save 'some message'

这会将您当前的更改存储在您的存储列表中。以上是最明确的 stash 命令版本,允许使用注释来描述您要存储的内容。您也可以只运行 git stash 而不执行其他任何操作,但不会存储任何消息。

您可以使用...浏览您的存储列表

git stash list

这将显示您所有的存储,它们在哪些分支上完成,以及每行开头的消息和该存储的标识符,看起来像 stash@{#} 其中 # 是它在存储数组中的位置。

要恢复存储(可以在任何分支上完成,无论最初创建存储的位置如何),您只需运行...

git stash apply stash@{#}

同样,# 是存储数组中的位置。如果您要恢复的存储在 0 位置 - 也就是说,如果它是最近的存储。然后你可以在不指定存储位置的情况下运行命令,git 会假设你的意思是最后一个:git stash apply

因此,例如,如果我发现自己在错误的分支上工作 - 我可能会运行以下命令序列。

git stash
git checkout <correct_branch>
git stash apply

在您的情况下,您在分支周围移动了一点,但同样的想法仍然适用。

希望这可以帮助。


git config --global alias.uncommit reset HEAD^ 只是取消提交重置的别名。相反,请执行 git config --global alias.uncommit 'reset HEAD^'
请注意,如果在 Windows 命令提示符中使用,则必须使用 ^^ 而不是 ^。
m
myselfmiqdad

我想你正在寻找这个

git reset --soft HEAD~1

它撤消最近的提交,同时将该提交中所做的更改保持在暂存状态。


谢谢。这对我有用。在 Windows 上调用 git reset HEAD^ 只会提示“更多?” - 不管什么意思
@Tyron ^ 是 DOS 中的转义字符。当与新行配对时,它用作前面命令的继续提示。键入 git reset HEAD^^ 应该可以在 Windows 上运行。
v
vallentin

是的,您可以在不删除更改的情况下删除您的提交:

git reset @~

有趣,紧凑的语法,我以前没有见过或使用过它。这与 git reset --softgit reset --keep 有何不同?
它对我不起作用: git reset @~ commit_hash 提交保持原样并且永远不会被删除
B
Bar Horing Amir

您正在寻找 git reset HEAD^ --softgit reset HEAD^ --mixed

docs 中所述,reset 命令有 3 种模式:

git reset HEAD^ --soft

撤消 git commit。工作树(项目文件夹)+索引(--cached)中仍然存在更改

git reset HEAD^ --mixed

撤消 git commit + git add。工作树中仍然存在更改

git reset HEAD^ --hard

就像您从未对代码库进行过这些更改一样。更改已从工作树中消失。


所有主要细节的最佳答案。
X
Xys

2020 简单方法:

git reset <commit_hash>

(您要保留的最后一次提交的提交哈希)。

如果提交被推送,您可以执行以下操作:

git push -f

您将在本地保留现在未提交的更改


当您说这是“2020 简单方法”时,是否暗示此方法在以前的版本中是不可能的?如果是这样,使用此方法需要哪个版本的 Git?
W
Wim Feijen

就我而言,我已经推送到了仓库。哎哟!

您可以通过执行以下操作恢复特定提交,同时将更改保留在本地文件中:

git revert -n <sha>

通过这种方式,我能够保留我需要的更改并撤消已经推送的提交。


就我而言,我需要恢复已推送到远程存储库的内容。更哎哟!最好的方法是先到 git revert bad-commit-sha,然后到 git revert -n revert-commit-just-created-sha,然后从那里修复。你让我半途而废。谢谢!
这似乎适得其反,不是吗?它会创建新的更改,这些更改对应于所选提交中所做更改的还原。如果您要提交这些新更改,您将撤消您实际上想要保留的工作。
因此使用了 -n 选项,该选项将还原将执行的更改暂存但未提交。然后,您可以选择保留或丢弃哪些还原更改
C
Community

对于那些使用 zsh 的人,您必须使用以下内容:

git reset --soft HEAD\^

此处解释:https://github.com/robbyrussell/oh-my-zsh/issues/449

如果 URL 失效,重要的部分是:

转义命令中的 ^ 您也可以使用 HEAD~ 这样您就不必每次都转义它。


我永远记不起这个命令,不得不谷歌搜索并找到我自己的答案哈哈哈
git reset HEAD^ 为我在 zsh 中工作,可能已修复。
@BenKolyaMansley 您正在运行什么版本的 zsh?
我正在使用 zsh 5.3 (x86_64-apple-darwin18.0)
嘿大家,我又来了,我已经看了很多次,最后把它扔进了我的 .zshrc,很多人可能会从中受益。示例:github.com/GregHilston/toolbox/blob/master/dot/zshrc#L147
n
nkharche

使用 git 2.9 (确切地说是 2.9.2.windows.1) git reset HEAD^ 提示更多;不确定这里的预期输入。请参考下面的截图

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

找到了其他解决方案 git reset HEAD~#numberOfCommits,我们可以使用该解决方案来选择您想要重置的本地提交的数量,方法是保持您的更改不变。因此,我们有机会丢弃所有本地提交以及有限数量的本地提交。

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

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


您可能需要转义 ^ 字符 - 尝试 git reset "HEAD^" 或 git reset HEAD\^
除此之外, git reset HEAD^^ 作为单个 ^ 工作,被视为新行。
R
Ruslan Osipov

另一种方法来做到这一点。

在临时提交的顶部添加提交,然后执行:

git rebase -i

将两个提交合并为一个(命令将打开带有明确说明的文本文件,编辑它)。


技术上正确,但远不如简单地执行 git reset HEAD^ 优雅。 Git rebase 在这里有很大的错误空间。
L
Louis Caron

在某些情况下,我只想在第一次提交时撤消对特定文件的更改,以将它们添加到第二次提交并拥有更清晰的 git 日志。

在这种情况下,我要做的是:

git checkout HEAD~1 <path_to_file_to_put_in_different_commit>
git add -u
git commit --amend --no-edit
git checkout HEAD@{1} <path_to_file_to_put_in_different_commit>
git commit -m "This is the new commit"

当然,即使在 rebase -i 中间,在提交拆分时带有编辑选项,这也能很好地工作。


W
Waaheeda

首先,您可以使用以下命令查看日志 -

git reflog

这显示了所有提交,然后找出您要撤消的提交以及与之关联的 Head 编号,然后输入以下命令

git reset HEAD@{#NumberOfCommitYouWantToUndo} 

例如git reset HEAD@{3}

git reset HEAD@{#} 显示重置后所有未暂存的更改