14

我使用git checkout --<dir_name(or)file_name>丢弃特定目录或文件中的所有更改。每当我这样做时,GIT 都会从存储库中检出目录(或)文件。

有没有办法告诉 GIT?,“不要覆盖更改,告诉我会发生什么。

类似于git clean -n(或) git clean --dry-run

更新: 在我执行之前git checkout --src/,我想看看哪些文件会被覆盖。我知道我们可以使用git status src/. 但是,拥有它不是很好git checkout -n --src/吗?用户没有太多的命令更改。

4

5 回答 5

6

Gitcheckout命令没有dry-run(或类似的)选项。但是,您可以使用 Gitls-files命令查看哪些工作目录文件不同于HEAD

git ls-files -dm -- src/

这将列出所有已删除或修改的文件,这些文件通常会被checkout.

另一种选择是使用 Gitdiff命令:

git diff --name-only HEAD -- src/

这列出了与 HEAD 不同的所有文件,并将在checkout.

如果这是经常做的事情,您可能需要创建一个alias

git config --global alias.lco "diff --name-only HEAD"

然后你可以使用:

git lco -- src/
于 2012-07-03T13:30:05.897 回答
5

你可以跑

$ git checkout --patch -- <files>

它会询问每个差异是否要“检查”该差异。如果您对每个提示都说“不”,那么它不会受到影响。

于 2012-07-03T11:44:59.517 回答
2

您需要为任何命令提供试运行选项,而不管假设的想法是“您不需要试运行以进行结帐,因为您可以通过其他方式获得差异列表”。

您不希望通过试运行选项来获取差异列表,而是希望通过试运行来验证“当我按下 Enter 时会发生什么?” 在你真正做到之前。它们是有区别的。如果您所做的只是阅读了手册,那么您正在测试程序的实际/准确行为时可能存在一些歧义。

我有一个奇怪的项目,其中 repo 位于“/”中。所以,有一个 '/.git' 目录和 '/.gitignore' 和 '/.gitmodules' 文件。/.gitignore 和 /.gitmodules 文件在 repo 中被跟踪,这是一个问题,因为即使开发人员用户有权编辑文件,他们仍然没有 git 删除和重新创建文件的权限,因为 don't 和 can't 对 '/' 本身具有写权限。如果 git 就地编辑文件不会有问题,但 git 会删除和替换,因为用户收到 git 无法取消链接文件的错误。在开发对我们的 repo 配置进行更改的过程中,以及开发人员在未来消除这个问题的一些指导,一路上我想知道这个命令会做什么:

git checkout master -- /.git*

和其他可能的变化,如

git checkout master -- '/.git*'

和其他人,更改 shell globbing 和/或查看 git 本身如何解释最终的 filespec 值。如果我从 shell 中转义一个“*”,git 会扩展一个“*”,还是会将其视为文字?如果它扩展它,它会包含“/.git/”目录吗?如果它扩展它,是否有一些我可以使用的正则表达式语法,这意味着“任何单个非空字符”,如“。” 在正则表达式或“?” 在外壳通配符中?等等等等

我不想知道哪些文件不同,我想测试 git 的确切行为以找到不寻常命令或命令集的最佳/最简单版本。

为此,您真的需要一个试运行选项。我已经知道哪些文件不同。在这种情况下,许多文件会有所不同,我不想要其中任何一个。我只想要 /.gitignore 和 /.gitmodules 而没有别的。

在这种情况下,我知道我可以通过简单地在命令行上明确指定它们来做到这一点。

git checkout master -- /.gitignore /.gitmodules

但我想看看是否有更短的通配语法可以自动获取它们,但理想情况下,不包括 /.git 目录。理想情况下,我想弄清楚我可以摆脱的最简单的形式。我知道我可以使用 shell 进行一些花哨且非常具体的扩展,但如果像 '/git*' 这样的东西有效,我宁愿使用它而不是 '/git{i,m}*'

这个特殊的任务很小,有几个简单的答案。请不要告诉我在没有“git checkout --dry-run”的情况下解决这个确切问题的方法,或者告诉我在 / 中进行回购是多么愚蠢,我也知道。我已经知道几种方法来完成我的直接工作。那不是重点。它可能很容易涉及更多文件或更复杂的 globbing 模式,因此仅明确列出文件就不会那么方便,或者,它可能是一些完全不同类型的问题。

关键是,一般来说,适用于任何地方的任何命令,包括 git checkout,总是有一个用于测试程序本身行为的空运行选项。阅读手册或 --help 并不能回答空运行回答的问题。

于 2017-08-28T20:16:21.140 回答
1

不确定,但作为一种解决方法,你当时git stash -u不能吗?git applygit checkout

如果您不满意,您可以随时恢复到藏匿处。

于 2012-07-03T08:10:06.707 回答
0

如果您想避免交互性(例如“对每个提示说不”),请使用git diff. 如果您想准确回答您的问题,请使用git diff -R. 如果您只想要文件名,请使用git diff --name-only.

如果没有该-R标志,git diff将以补丁格式报告您的工作树和索引之间的所有差异,即您在发布时看到的格式git show <commit>-R反转输出,向您展示删除更改后会发生什么,就好像删除本身就是一个补丁一样。考虑一个例子:

git init /tmp/test && cd /tmp/test
echo "old line">file
git add .
git commit -m "Initial commit"
echo "new line">file

现在发行git diff没有任何标志。你应该得到:

$ git diff
diff --git a/file b/file
index 0906fba..86ba82a 100644
--- a/file
+++ b/file
@@ -1 +1 @@
-old line
+new line

坦率地说,我发现输出很容易解析我从不使用-R标志。如果您经常发出git diff命令(我发现它是我最常用的命令之一),则可能不需要反向输出。同样,出于此答案的目的,请尝试:

$ git diff -R
git diff -R
diff --git b/file a/file
index 86ba82a..0906fba 100644
--- b/file
+++ a/file
@@ -1 +1 @@
-new line
+old line

该输出准确地描述了您寻求的内容:“不要覆盖更改,只需告诉我会发生什么。”

默认情况下,该命令会将您的整个工作目录与索引进行比较。它会显示每个修改文件中的差异。假设您只想查看一个文件的效果。这很容易。只需使用您已经在使用的相同的双破折号命名法:

git diff -- <file>

你会发现git diff它是 git 中最有用、可扩展的命令之一,你可以用它来做各种有用的事情。您可以使用它来比较两个提交、两个分支或两个文件。我最近的“最喜欢的疯狂 git 操作”是管道git diffgit apply. 前者产生可理解的补丁。后者应用它们。当它们结合在一起时,你重写历史的能力几乎是无限的——当然,在本地,永远不要重写共享的历史。考虑另一个例子,在这一点上离题但很有趣(如果你喜欢这种事情)。从我们的测试存储库,上面:

git add .
git commit -m "Second commit"
echo "even newer line">file
git add .
git commit -m "Third commit"

你知道吗?我不太喜欢第二次提交。它的实现是错误的。它正在打破测试。我不想分享它。尽管如此,我确实想保留“第二次提交”提交消息,因为这真的很难输入。我可以用 重新设置它git rebase -i HEAD~2,但这涉及打开编辑器、删除提交、编辑另一个和(呃)复制/粘贴。开发人员要做什么?这个怎么样:

git checkout ":/Initial" ;# get back to the first commit
git diff HEAD ":/Third" | git apply ;# apply the diff between the first and third commit
git add . ;# add the result
git commit -C ":/Second" ;# with second commit's message
git checkout -B master HEAD ;# and replace old 'master'

结果与git rebase. 我只是设法避免了交互式会话,并且不必使用编辑器。是不是矫枉过正?可能,但它确实很有趣。此外,很容易构建更复杂的用例,尤其是当您组合git diffgit applygit add -p.

于 2012-07-03T14:27:09.190 回答