这两种移动分支的方式有区别吗?

时间:2014-08-25 03:28:20

标签: git git-branch

我正在关注交互式LearnGitBranching教程,并遇到了两种移动分支的方法。我想确定我没有遗漏任何东西。

之间是否存在差异:

 git branch -f master master^ 

并假设HEAD指向master

git reset HEAD^

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

谢天谢地!

1 个答案:

答案 0 :(得分:2)

正如a comment中提到的genisage,git reset有多种模式。

忽略所有模式及其操作,第一个问题的答案是:如果HEAD引用master,您将master移至另一个提交git branch然后是的,这实现了与master间接移动git reset相同的事情。但是:

  1. 我们不能简单地忽略reset的选项。
  2. 我们也开始回答“如果HEAD引用master”。如果没有怎么办?
  3. 特别是,对于第1点,git reset的默认模式为--mixedreset命令可以,并且在这种情况下,不仅仅是移动分支尖端。它还可以更新git的索引(也称为“临时区域”)。

    你可以 - 事实上,可能应该将git的索引/暂存区域视为“下次运行git commit时git准备提交的内容”。当你git add一个文件让git为下次提交提取更改时,git会读取该文件的当前工作树版本,然后将 1 写入索引。

    通过更改索引内容以匹配提交,git reset对(--mixed)做什么(或可以做什么,以及对git reset --mixed HEAD^做什么)是撤消这种索引修改复位到。也就是说,git branch不仅支持分支一次提交,而且将所有索引内容重置为逐个提交的提交。 git reset命令不会触及索引。

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

    为了完整起见,值得注意的是git reset --hard甚至超过git reset --mixed:它不仅更新分支提示并重置索引,还会“重置”您的工作树,使其成为看起来像新的目标提交。

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

    • git reset --soft HEAD^支持你一次提交,而不更改索引或工作树,以便新的git commit提供一个新的分支提示,其内容与提交的内容相同备份-过来。这允许你更改提交消息。 2 这与git commit --amend完全相同,除了后者实际上更容易;所以这种用法不再常见(这是git commit --amend选项之前的做法。

    • git reset --mixed -- <path>“移动”你当前的提交 - 也就是说,它会重写当前分支以指向它已经指向的位置,这是一个无操作 - 但会重置索引,而不会改变工作树。这样,您就可以“撤消”git addgit rm --cached 3 通常它拼写为git reset <path>,因为--mixed是默认值。

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

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


    1 实际上,git将文件(或“blob”)写入存储库,而不是写入索引。在编写blob的过程中,git还会计算得到的SHA-1:对象的“真实名称”。 (所有存储库对象都是由它们的“真实名称”SHA-1s找到。存储库充当一个简单的键值存储,键是SHA-1,值是对象:文件aka“blob”,或者tree,或commit,或annotated-tag-object。)SHA-1进入索引,连同文件名和执行权限位。根据需要,索引稍后在提交时转换为一个或多个git“tree”对象;这些树对象包含各种文件名,modse / execute-permissions和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 --soft vs git branch -f