如何做你想做的事情
问题概述: 当你使用 git checkout commit-hash path
(在这种情况下是 git checkout a0c53b9 u-boot/
) 时,Git会提取该路径(在这种情况下是一个充满文件的目录),但不会git rm
任何当前位于该目录中但不在该特定提交中的文件。 这意味着如果您现在进行新的提交,它将具有旧的u-boot代码,但将新文件与旧代码混合。
简单的解决方法是,首先确保您不需要这些文件中的任何内容——即没有未提交的工作需要保存——然后只需
git rm -rf u-boot/
(而不是常规的
rm
)整个目录。这将清除工作树并安排所有文件进行删除,但在实际提交任何内容之前,
现在运行
git checkout a0c53b9 u-boot/
,这将重新填充提交
a0c53b9
中的
u-boot/
文件的索引和工作树。那些没有旧版本的已删除文件仍然被删除,而具有旧版本的已删除文件则从旧版本中恢复。
背景,或者简洁版:为什么Git会表现出这样的行为
git checkout
命令实际上是几个不同的命令(取决于如何计算):
git checkout name
(其中name
是有效的、存在的分支名称)将当前提交切换到新提交,使您处于给定的分支name
上。即使根据gitrevisions
,name
应该解析为提交ID而不是分支名称,这也是正确的(尽管这种情况非常罕见,不应该发生)。如果某些工作树文件会被覆盖,则此操作可能失败(但-f
将强制执行切换)。
git checkout hash
将当前提交切换到新提交,使您退出任何分支(进入“游离 HEAD”模式)。否则它与提供分支名称相同。 hash
可以是解析为提交ID的任何内容,包括标签或远程跟踪分支名称;但不能是现有的分支名称,因为那将属于第一种情况。
git checkout -b name
使用给定的name
创建一个新分支(其他参数可以影响分支的创建方式)。它通常不会失败,因为您通常会在当前提交处创建一个新分支,这意味着只需要更改HEAD
间接引用:工作树中未提交的工作仍然未提交。
git checkout -- path
将一些文件从索引中提取到工作树中,覆盖任何未提交的工作。请注意,如果您先前使用git add
添加了一个path
,然后修改了该文件的一些内容,则此操作将恢复您添加的版本,而不是HEAD
提交中的版本。
git checkout hash
-- path
将一些文件从给定的hash
中提取到工作树中,并通过索引将它们写入(即,索引条目也会更新)。否则它与之前的(从索引检出)方法相同:在两种情况下,当命令完成时,工作树与索引匹配。 hash
参数可以是Git可以解析为树的任何内容:这包括分支、标签和远程跟踪分支名称。Git不会更改当前提交,只会更改索引和工作树。
请注意,前三种列出的形式小心地避免了对工作目录中的工作进行破坏,而最后两种则故意破坏了工作。 (我个人认为至少这两种模式应该是不同的命令。也就是说,如果
git <something-like-checkout>
始终是安全的,而
git <something-like-clobbber>
是“不安全”的命令,那就更容易记住何时要小心。)
当您执行此操作时:
git checkout a0c53b9 u-boot/
你使用的是最后一种形式的
git checkout
,即
git checkout hash -- path
。(这里的双破折号实际上并不是必需的。它将哈希值与路径分开,并且在使用第四种形式时至少可能是必需的。假设您想要从索引中检出一个名为
f33dc47
的Leet-speak文件。但是文件名
f33dca7
——1337中的“feed cat”也是有效的哈希前缀。双破折号是告诉git您正在执行第四种形式的checkout而不是第二种形式的方法。)
当您使用
git checkout
的最后两种形式之一时,git不会更改您当前的提交,它只是提取了一些文件。在这种情况下,git不会删除文件。您提取的文件是“
u-boot/
中的所有内容”,正如您所看到的,git确实更新了这些文件,但没有删除
u-boot/
中的任何其他文件。这是
git checkout
的正确行为。
在您的情况下,您想要创建一个新的提交,其中包含“新的其他所有内容,但是旧的
u-boot/
,包括没有随之而来的新的
u-boot/
文件”。那么,如何清除目录,以避免多余的文件呢?答案在于注意到
git checkout hash -- path
会将索引写入工作树中;因此,如果您首先清空该目录中所有文件的工作树和索引,然后从旧提交重新填充两者,您将得到所需的结果。
rm -rf u-boot/
,直到我意识到实际上是git rm -rf u-boot/
,而且那个目录下也没有未提交的更改。您回答中对我有帮助的部分是"在你的情况下..."段落以及后续的命令。(我已经编辑了我的问题来纠正您指出的错误哈希值。) - undefined