等同于:git reset --hard --patch?

8
有没有类似于“git reset --hard --patch”的操作?(因为这会导致错误:fatal: --patch is incompatible with --{hard,mixed,soft})。换句话说,如何执行git reset --patch,但是立即丢弃“未暂存”的更改?(特别是对于新添加的文件-我不想让它们散落在我的工作目录中,因为我已经有很多其他东西了...所以很难找到新垃圾并手动删除它...)是否有“多个暂存区”,可以像使用--patch一样轻松地将块传递给另一个?请注意,我不希望任何文件显示为“Changes to be committed”中的“new file”被移动到“Untracked files”。对于其中的每个文件,我都希望能够明确地决定是否要保留它们或永久丢弃它们(即从磁盘中删除)。换句话说:我正在尝试将提交分为两部分,但其中一些是“新文件”。我想将其中一些移动到提交的“另一半”。但我不想逐个从“Untracked files”列表中添加它们。请注意,我有许多“未跟踪的文件”在周围,我不想将它们添加到.gitignore或.git/info/exclude中,因为有一些原因。

嗯,我开始觉得也许 git stash --patch 可以成为我的解决方案……不过还不确定具体怎么做。 - akavel
@user3159253 将一个提交拆分成多个提交,使用高精度(因此使用 --patch),在此过程中不会丢失新添加的文件的轨迹。 - akavel
错误,要拆分提交,需要使用不带 --hardgit reset 命令,对吧? - Matthieu Moy
请注意,我明确表示(尽管用不同的措辞,可能不够清楚)我不希望在提交中添加的任何文件出现在git status输出的“未跟踪文件”中 - akavel
5个回答

10

git reset --hard 的作用是将您带回到一个干净的状态,在任何情况下都可以使用:无论您是否有暂存或未暂存的更改,是否在索引中存在冲突... 在这些情况下,使用 --patch 选项并不真正有意义。

实际上,git reset --hard 对于最终用户通常不是一个好主意:它不仅会丢弃更改,而且以不可恢复的方式进行。相反,git stash 会保留更改。它既可以用于“我想暂时把这些更改放在一边,很快就会拿回来” ,也可以用于“我知道我要永久地丢弃这些更改,但我会保留备份以防万一”。

正如您已经注意到的那样,git stash 有一个 --patch 选项,因此它显然是一个好的解决方案。另一种选择是使用 git reset --patch(不带 --hard)将您的索引置于所需的状态,然后使用 git stash --keep-index 使工作树与索引匹配。

如果更改足够大,您需要担心磁盘空间的使用情况,或者如果您只是不想在储藏列表中添加杂物,那么您可以运行 git stash drop 来删除储藏条目。


不幸的是,git stash --patch 似乎跳过了任何新添加的文件(即在“Changes to be committed”中显示为“new file”的文件)。我还尝试了 git stash --patch --keep-index,但这会将新添加的文件移回到未跟踪状态,这也不是我想要的。 - akavel
更新了我的答案,包括使用reset + stash -k的另一种解决方案。 - Matthieu Moy
但是,如果我在 git reset -p 之后有“新文件”在暂存区中,并且我取消暂存它们,它们将变为未跟踪的,对吗?所以,即使使用 -k,git stash 也不会从工作目录中删除它们,对吗? - akavel
@MatthieuMoy 我不同意,--hard 是需要小心使用的东西,但当你有一些明确要丢弃的更改时是很有用的。这种情况我经常会遇到。将其添加到存储区会很麻烦,我不想在我的存储区里留下一堆垃圾。git reset hard --patch 可以让你轻松地丢弃文件的部分更改等,并让你确定你要丢弃的内容。我认为从功能上来说这是非常合理的。 - csga5000
正如我所写的,将东西保存在你的存储库中基本上会占用硬盘上的几千字节,这并不意味着你必须在某一天使用它们。你可能没有这样做,但我敢打赌,总有一天你会用 git reset --hard 删除重要的东西。我经常看到用户说“我知道我在做什么,我不需要这种安全性”,但很少有用户实际上从未需要过任何安全性。就像古话说的“Unix用户分为两类:已经作为root犯过错误的人和即将犯错误的人”。现在,如果不想要这种安全性,那是你的选择;-)。 - Matthieu Moy
显示剩余3条评论

1

发现这个问题是为了做同样的事情,然后发现六年后的Git现在有了restore命令。

git restore -p -s HEAD正好满足了我的需求,让我可以交互地将工作目录的部分内容重置为HEAD。

虽然它仍被标记为实验性的,但看起来至少在2019年之前就已经引入了https://dev59.com/8VMH5IYBdhLWcg3w1j31#58003889,所以现在应该相当稳定。


0
我正在尝试将一个提交分成两个,但其中有一些“新文件”。其中一些我想移动到提交的“另一半”中。但我不想从“未跟踪文件”列表中逐个添加它们。
now=`git write-tree`       # snapshot current state w/o bothering with a commit
git checkout --patch @     # undo whatever needs undoing
git commit                 # and that's the first commit
git read-tree -um $now     # now the original state's back in index and work tree

0

git reset -p 撤销对 索引 的更改,但保留它们在工作树中。这是 git add -p 的反义词。

如果您想撤消对 工作树 的更改,可以选择性地将它们复制到存储区,审核存储区,最后删除存储区:

git stash -p        # select hunks
git stash list -p   # review you don't shoot at foot, rollback with "git stash pop"
git stash drop      # forget the junk you wanted to remove

-1
我找到了一个解决办法:将repo克隆到一个临时目录,然后可以在那里使用git reset -pgit add .编辑我想要的提交,而不会受到额外未跟踪文件的干扰。
然而,有一些明显的缺点,包括钩子没有自动克隆。并且任何硬编码的路径都不能正常工作(包括PATH、GOPATH、IDE中的项目等)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接