UPDATE²:在Git 2.23(2019年8月)中,有一个新命令Git restore可以做到这一点,请参阅公认的答案。 更新:从Git 1.8.3开始,这将更加直观,请参见我自己的答案。 想象一下下面的用例:我想去掉Git工作树中特定子目录中的所有更改,保留所有其他子目录不变。 我可以做git结账,但是git结账。添加稀疏签出排除的目录 git重置很难,但它不允许我对子目录进行重置:
> git reset --hard . fatal: Cannot do hard reset with paths.
再说一遍:为什么git不能按路径进行硬/软重置? 我可以使用git diff subdir | patch-p1-R反向修补当前状态,但这是一种相当奇怪的方法。 此操作的正确Git命令是什么? 下面的脚本说明了该问题。在How to make files注释下面插入适当的命令——当前命令将恢复稀疏签出应该排除的文件a/c/ac。请注意,我不想显式还原a/a和a/b,我只“知道”a,并希望还原下面的所有内容。编辑:我也不“知道”b,或者哪些其他目录与a位于同一级别。
#!/bin/sh rm -rf repo; git init repo; cd repo for f in a b; do for g in a b c; do mkdir -p $f/$g touch $f/$g/$f$g git add $f/$g git commit -m "added $f/$g" done done git config core.sparsecheckout true echo a/a > .git/info/sparse-checkout echo a/b >> .git/info/sparse-checkout echo b/a >> .git/info/sparse-checkout git read-tree -m -u HEAD echo "After read-tree:" find * -type f rm a/a/aa rm a/b/ab echo >> b/a/ba echo "After modifying:" find * -type f git status # How to make files a/* reappear without changing b and without recreating a/c? git checkout -- a echo "After checkout:" git status find * -type f
有了Git 2.23(2019年8月),您就有了新的命令Git restore(此处也有介绍)
git restore --source=HEAD --staged --worktree -- aDirectory # or, shorter git restore -s@ -SW -- aDirectory
这将用HEAD内容替换索引树和工作树,就像重置一样——很难,但对于特定的路径。 原始答案(2013年) 请注意(如Dan Fabulich所述): git签出–不会进行硬重置:它将工作树内容替换为分段内容。 git checkout HEAD–对路径进行硬重置,用HEAD提交的版本替换索引和工作树。 正如Ajedi32所回答的那样,两个签出表单都不会删除目标修订版中删除的文件。 如果您在工作树中有额外的文件,而这些文件在HEAD中不存在,那么git签出头–将不会删除它们。 注意:使用git checkout-overlay HEAD–(git 2.22,2019年第1季度),将删除索引树和工作树中出现的文件,但不在中的文件,以使它们精确匹配。 但这种签出可以遵循git更新索引——跳过worktree(对于那些您想要忽略的目录)
根据 Git 开发人员 Duy Nguyen 的说法,他善意地实现了该功能和兼容性开关,从Git 1.8.3 开始,以下工作按预期工作:
git checkout -- a
(a您要硬重置的目录在哪里)。可以通过以下方式访问原始行为
a
git checkout --ignore-skip-worktree-bits -- a