这两种移动树枝的方式有区别吗



我在学习交互式LearnGitBranching教程时,发现了在分支中移动的两种方法。我想确保我没有错过任何东西。

之间有区别吗

 git branch -f master master^ 

并且,假设HEAD指向master,则

git reset HEAD^

而且,如果他们做同样的事情,为什么有reset命令呢?这是否意味着它只是git branch -f的简写?

谢谢!

天才在评论中指出,git reset有多种模式。

忽略所有模式及其作用,第一个问题的答案是:如果HEAD引用master,并且您使用git branchmaster移动到另一个提交,那么是的,这实现了与使用git reset间接移动master相同的效果。但是:

  1. 我们不能简单地忽略reset的选项
  2. 我们还以"如果HEAD指的是master"开始回答。如果没有呢

特别地,对于点#1,git reset的默认模式是--mixedreset命令不仅可以移动分支尖端,而且在这种情况下确实可以。它还可以更新git的索引(也称为"暂存区")。

您可以——事实上,可能应该——将git的索引/暂存区视为"git准备在下次运行git commit时提交什么"。当您git add一个文件以使git为下一次提交拾取更改时,git读取该文件的当前工作树版本,然后将1写入索引。

git reset所做的(或可以做的,以及对--mixed所做的)是撤消这种索引修改,方法是更改索引内容以匹配您重置为的提交。也就是说,git reset --mixed HEAD^不仅备份分支一次提交,而且将所有索引内容重置为备份一次提交。git branch命令不接触索引。

通过使用--soft选项,可以使git reset不接触索引。在这种情况下,它确实做了与git branch -f相同的事情——尽管如第2点所述,只有当HEAD引用master时,这才有效。如果你想在不使用git reset的情况下进行软重置,你的第一步是找出HEAD指向的分支(如果有的话)。只有这样,你才能更新分支(然后,只有当你没有处于"分离的HEAD"模式时)。

为了完整性,这里值得注意的是,git reset --hardgit reset --mixed做得更多:它不仅更新分支提示和重置索引,还"重置"了工作树,使其看起来像新的目标提交。

还值得补充的是,git reset的几个常见用途故意只使用了它的一些动作:

  • git reset --soft HEAD^在不更改索引或工作树的情况下为您备份一次提交,因此新的git commit提供了一个新的分支提示,其内容与您刚刚备份的提交内容相同。这样可以更改提交消息2这与git commit --amend完全相同,只是后者实际上更容易;因此这种用法不再常见(这是在git commit--amend选项之前的做法)。

  • git reset --mixed -- <path>将您"移动"到当前提交——也就是说,它重写当前分支以指向它已经指向的位置,这是一个非操作——但重置索引,而不更改工作树。这样可以"撤消"git addgit rm --cached3通常它只是拼写为git reset <path>,因为--mixed是默认值。

  • git reset --hardgit reset --hard <path>再次"移动"您,但根本不移动,而是重置索引并恢复工作树版本。

reset命令有几个额外的选项(--merge--keep;还有-p)不太适合这种模式。不过,我只是在这里忽略它们,以免这个答案变得太长。

<小时>

1实际上,git将文件(或"blob")写入存储库,而不是索引。在写入blob的过程中,git还计算得到的SHA-1:对象的"真实名称"。(所有存储库对象都是通过它们的"真名"SHA-1找到的。存储库充当一个简单的键值存储,其中键是SHA-1,值是对象:文件aka"blob"、树、提交或注释标记对象。)SHA-1与文件名和执行权限位一起进入索引。稍后,根据需要,在提交时将索引转换为一个或多个git"树"对象;这些树对象包含各种文件名、modse/execute权限和SHA-1。

2更准确地说,您使用更正的消息进行新的、不同的提交。这也是git commit --amend的作用。旧的(修订前)提交仍在存储库中,具有相同的SHA-1;具有不同消息和不同时间戳的新提交具有不同的SHA-1,即使它从同一索引开始,因此具有相同的树。

3常规(非--cachedgit rm已从工作树中删除该文件,因此git reset --mixed不会执行此操作。git reset --hard <path>会执行此操作,或者您可以使用git checkout HEAD -- <path>来取回该文件。后者"写入"索引,因此这些最终在命令方面几乎是多余的,就像git reset --softgit branch -f一样。

最新更新