【问题标题】:What does the ~1 mean in this git reset command?这个 git reset 命令中的 ~1 是什么意思?
【发布时间】:2013-08-08 18:57:50
【问题描述】:

git 重置 HEAD~1

我的印象是 ~1 的意思是:从 HEAD 开始,跟随 1 链接,并将 HEAD 标记设置为那个新的提交节点。我期待着

git 重置 HEAD~2

跟随 2 个链接,然后设置 HEAD 标记。但是,如果我尝试它,我会得到一个错误:

$ git reflog
c83bbda HEAD@{0}: reset: moving to HEAD~1
44c3540 HEAD@{1}: commit: you will be garbage soon
c83bbda HEAD@{2}: reset: moving to HEAD~1
aee7955 HEAD@{3}: commit: back to 4 lines
c83bbda HEAD@{4}: reset: moving to HEAD~1
19ec1d5 HEAD@{5}: commit: 3 lines
c83bbda HEAD@{6}: reset: moving to HEAD~1
a049538 HEAD@{7}: commit: added new line
c83bbda HEAD@{8}: commit (initial): first commit


$ git reset --hard HEAD~2
fatal: ambiguous argument 'HEAD~2': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

显然我弄错了,但是 git reset 的文档页面对于澄清这一点并不是很有用。那么,~1 是什么意思,我为什么需要它?

【问题讨论】:

标签: git


【解决方案1】:

您在运行git reset --hard HEAD~2 时收到此错误消息

fatal: ambiguous argument 'HEAD~2': unknown revision or path not in the working tree.

因为您正在尝试将工作副本重置为不存在的提交。根据您的 reflog,您在运行此命令时已签出初始 root 提交:

$ git reflog
c83bbda HEAD@{0}: reset: moving to HEAD~1
# etc ...
c83bbda HEAD@{8}: commit (initial): first commit

所以根据上面的 reflog,你是当前的工作副本,即HEAD,是你的第一次提交,所以通过从这里执行git reset --hard head~2,你告诉 Git 返回 2 次提交 在你的第一次提交之前,这当然不能这样做,因为在你的第一次提交之前什么都不存在:

fatal: ambiguous argument 'HEAD~2': unknown revision or path not in the working tree.

【讨论】:

    【解决方案2】:

    有关如何指定提交的更多详细信息,请参阅 git help revisionsGit - Revision Selection

    <rev>~<n>, e.g. master~3
    

    修订参数的后缀~&lt;n&gt; 表示提交对象是&lt;n&gt;th 命名提交对象的世代祖先,仅在第一个父母之后。 IE。 &lt;rev&gt;~3 等价于&lt;rev&gt;^^^ 等价于&lt;rev&gt;^1^1^1

    此语法可用于大多数 Git 命令,因此它不特定于 git reset

    【讨论】:

      【解决方案3】:

      HEAD~1 是“HEAD 的第一个父项”,而HEAD~2 是“HEAD 的第一个父项的第一个父项,依此类推(所以对于某些 n,HEAD~n 就像 @987654327 @ 后跟 n 个 ^ 符号,没有数字)。同样,所有细节都在 git-rev-parse 手册页中。

      在将git reset 与“从HEAD 向后计数的修订版本”混合时要小心。 git reset 通常会更改 HEAD 的值,例如:

      $ git checkout master    # now on tip of "master" branch
      $ git branch save master # copy branch tip to another label, for safekeeping
      $ git reset HEAD^        # or git reset HEAD~1
      

      HEAD(和master)移动到它的第一个父级。命名该父级的另一种方法是save^,还有一种是save~1。不过,在移动完成后,HEAD 现在命名该父版本,因此 HEAD^ 命名 父版本:

      $ git reset HEAD^
      

      让你后退一步,所以 masterHEAD 现在命名与 save~2 命名的相同提交。使用git rev-parse 很容易看到这一点,它告诉您某些符号名称映射到的提交 ID:

      $ git rev-parse save~2 master
      0f5a13497dd3da8aff8e452c8f56630f83253e79
      0f5a13497dd3da8aff8e452c8f56630f83253e79
      

      此时,您可以使用以下命令将master 恢复到保存点:

      $ git reset save
      

      这会将HEADmaster 移回保存的修订版,然后您可以根据需要安全地删除save

      $ git branch -d save
      

      请注意,您也可以使用git tag 保存保存点:分支和标签之间的唯一区别是“在分支上”时新签入的行为(标签不移动,分支移动) 和结帐(标签将您置于“分离的 HEAD”= 非分支状态,分支名称将您置于“分支”状态)。

      【讨论】:

        【解决方案4】:

        git reser --hard HEAD~1 删除当前分支的最后 1 个(或任何其他数字)提交,如下所示
        git reset HEAD ... 删除最后一个提交
        git reset HEAD~1 ... 删除最后 2 次提交
        等等

        【讨论】:

        • 几乎:git reset HEAD 不会删除提交。 reset 的默认值是 reset --mixed,它会重置索引但不会更改工作树,并且在任何情况下,HEAD 都会命名为“您现在所在的位置”,因此这也不会移动分支标签。因此,它实现的是撤消任何git adds 和/或git rm --cached 的效果。 (说它删除提交也是言过其实,它只是通过更改分支名称的SHA-1值使提交出现消失。它们最终消失了通过git gc.)
        猜你喜欢
        • 1970-01-01
        • 2023-04-06
        • 1970-01-01
        • 2013-03-04
        • 2019-08-30
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        相关资源
        最近更新 更多