我看过了这个stackoverflow链接,但我认为我要问的是在结帐cmd中使用HEAD
的细微差别,因为他们的建议似乎不起作用:>
https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/connections-api
git checkout HEAD -- .
也会清理我的暂存区。
此外,第二个答案是关于已添加到登台区域的已删除文件的信息,
似乎又回来了git checkout HEAD -- .
有没有可能得到不同结果的情况?
答案 0 :(得分:3)
是的,除了.
所暗示的以外(如果您不在存储库的顶层),还有一个区别。我什至不会宣称只有 差异。只需显示一个示例,看看它们是不同的即可。
首先创建一个至少具有一次提交的新存储库(按照我的习惯,这里我做了两次):
$ mkdir treset
$ cd treset
$ git init
Initialized empty Git repository in ...
$ echo 'for testing reset vs checkout' > README
$ git add README
$ git commit -m 'initial commit'
[master (root-commit) 058b755] initial commit
1 file changed, 1 insertion(+)
create mode 100644 README
$ echo contents for file a > file-a
$ echo contents for file b > file-b
git commit -m 'add files'
[master f505609] add files
2 files changed, 2 insertions(+)
create mode 100644 file-a
create mode 100644 file-b
这时,HEAD
和索引匹配(均包含提交f505609
的内容),工作树也包含与提交匹配的(正常格式)文件。现在,我们添加一个 new 文件,并将其复制到索引中:
$ echo 'uncommitted file' > foo
$ git add foo
从技术上讲,git add foo
在存储库中创建了 blob对象 a9e2570d6af8c05b57e2cefecaebeedfabc98bf2
,然后将该哈希ID放入索引:
$ git ls-files --stage
100644 e16f62b2e75cf86a6f54adcfddcfd77140f238b9 0 README
100644 881d9334f4593efc7bab0dd536348abf47efed5c 0 file-a
100644 fa438bc26ce6b7a8f574bad9e63b83c912a824b9 0 file-b
100644 a9e2570d6af8c05b57e2cefecaebeedfabc98bf2 0 foo
(由于文件foo
的已知内容,该blob对象的哈希ID是可预测的。其他三个文件也是如此,但实际上它们已提交,因此这些blob对象是永久的。如果我们从未实际提交foo
的那个,则可以将其GC起来,而从索引中删除该条目。)
git checkout HEAD
如果我们使用git checkout HEAD
,我们会将Git从HEAD
定向到 copy 到索引中,然后将它们扩展为普通的工作树文件。 HEAD
包含三个文件(README
,file-a
和file-b
),因此可以做到这一点,并使用它们已经拥有的内容更新这三个工作树文件,因此没有明显的效果。 1
$ git checkout HEAD -- .; ls
file-a file-b foo README
请注意,文件foo
保留在索引中(再次运行git ls-files
以查看)和工作树中。
1 除非,也就是说,我们通过可用的任何OS级工具来检查文件修改时间或执行的系统调用之类的事情。在这种情况下,我们可以判断Git是否确实覆盖了工作树文件。在我的系统上,它实际上没有,因为索引哈希与HEAD
哈希匹配,并且缓存在索引中的stat
数据与来自工作树文件,因此它不会打扰。但是在原理中,Git将stat
复制到索引,然后将索引复制到工作树,并且如果有必要基于哈希和/或统计数据,则Git实际上会碰到这里的工作树文件。
HEAD
如果我们告诉Git重置索引以匹配当前提交,并重置工作树以匹配对索引的更改,则操作是不同的。这次,Git检查索引并发现文件git reset --hard
存在,而提交中却没有。因此,Git从索引中删除文件foo
,并相应地更新工作树:
foo
文件$ git reset --hard HEAD; ls
HEAD is now at f505609 add files
file-a file-b README
从工作树中消失了。
如果我们要使用foo
,Git将从索引中删除git reset --mixed HEAD
,但不会从工作树中删除。 (这种重设的默认动作(还有许多其他种类)是foo
。)
--mixed
使用新的Git 2.23+ git restore
命令,我们可以分别控制索引和工作树。首先,我们必须将git restore
放回索引和工作树中:
foo
我们现在可以选择是否将$ echo 'uncommitted file' > foo
$ git add foo
复制到索引,以及是否类似地管理工作树。 Its documentation也更加明确:
如果跟踪了一条路径,但该路径在还原源中不存在,则会将其删除以匹配该源。
要“跟踪”路径的意思是该路径在索引中。在这种情况下,HEAD
现在在索引中(由于foo
),因此将对其进行跟踪。如果我们从git add
恢复索引,则HEAD
将从索引中删除,就像foo
或git reset --hard
一样。因此,让我们尝试VonC's command,但使用git reset --mixed
(当前目录和所有子目录) 2 作为路径名,在这里:
.
因此,您可以看到它与$ git restore --source HEAD --staged --worktree .
$ ls
file-a file-b README
具有相同的作用。与git reset --hard
不同,git reset
仅具有一项工作-尽管有两个部分,所以我们不必担心其他操作模式。
(这就是为什么同时添加了git restore
和git switch
的原因:大多数情况下,您可以使用git restore
和{{1} },但他们只有一个工作[em] ,即使它有多个部分。相反,git checkout
有大约三到七个不同的工作,具体取决于您的计算方式,而{ {1}}的范围是大约3到大约5。 3 )
2 此特定存储库只有一个顶级目录,因此我们不必担心您在工作树中完成了git reset
。如果有的话,git checkout
意味着将其应用于git reset
文件,因此签出和重置将更加不同。
3 对于cd subdir
,请考虑:
.
)subdir/*
)git checkout
,但具有分支名称)虽然只有五个,但我们可以git checkout-index
和git checkout -m
进行操作,有些人可能希望将它们与通常的“从索引中提取”味道分开。当您添加 create分支(git checkout -m
)和强制重置分支(git checkout --ours
)时,我们可以得到更多。 {,git checkout --theirs
也具有创建和强制重置选项!
某些人当然可以像git checkout -b
一样将其中的一些或全部集中到一个操作中。这就是为什么我说“取决于您的计数”的原因。
对于git checkout -B
,请考虑:
git switch
即可重置索引和/或工作树git checkout
git reset
)HEAD
)HEAD
进行选择性修补(无法移动HEAD
)所有这些都集中在一个命令HEAD
下。
答案 1 :(得分:1)
为避免使用confusion,应使用新的实验性命令 git restore
(Gti 2.23 +,2019年8月)。
正如我在“ What is git restore
Command ? What is the different between git restore
and git reset
?”中所述,您可以指定使用git restore
恢复的内容。
这比在git checkout
中依靠HEAD或不依靠HEAD更为明确。
使用reset --hard
做git restore
:
git restore --source=HEAD --staged --worktree hello.c
或简称,它更实用,但可读性更差:
git restore -s@ -SW hello.c