当我在Git中指定祖先提交对象时,我对HEAD^HEAD~感到困惑。

两者都有一个“编号”版本,例如HEAD^3HEAD~2

它们对我来说似乎非常相似或相同,但是波浪号和插入符号之间是否有任何区别?

最佳答案

经验法则

  • 大部分时间都使用~-追溯许多代,通常是您想要的
  • 在 merge 提交上使用^-因为它们有两个或更多(直接) parent

  • 助记符:
  • 波浪形~的外观几乎是线性的,想要沿直线向后退
  • Caret ^建议道路上有趣的树或 fork 段

  • 蒂尔德
    “Specifying Revisions” section of the git rev-parse documentation定义~

    您可以进行任何提交的 parent ,而不仅仅是HEAD。您还可以追溯几代人:例如,master~2表示master分支尖端的祖 parent ,在 merge 提交时偏向于第一个父代。
    插入符号
    Git历史是非线性的:有向无环图(DAG)或树。对于只有一个 parent 的提交,rev~rev^表示同一件事。插入符选择器对于 merge 提交很有用,因为每个提交都是两个或多个 parent 的 child -并限制了从生物学借来的语言。HEAD^表示当前分支的尖端的第一个直接父代。 HEAD^HEAD^1的缩写,您也可以根据需要寻址HEAD^2等。 same section of the git rev-parse documentation将其定义为

    例子
    这些说明符或选择器可以任意链接,例如,英语topic~3^2是 merge 提交的第二个父级,它是分支topic当前尖端的曾祖 parent (返回三代)。
    aforementioned section of the git rev-parse documentation通过概念git历史记录跟踪许多路径。时间通常向下流动。提交D,F,B和A是 merge 提交。

    运行以下代码以创建一个git存储库,其历史记录与引用的插图匹配。
    #! /usr/bin/env perl
    
    use strict;
    use warnings;
    use subs qw/ postorder /;
    use File::Temp qw/ mkdtemp /;
    
    my %sha1;
    my %parents = (
      A => [ qw/ B C /               ],
      B => [ qw/     D E F /         ],
      C => [ qw/         F /         ],
      D => [ qw/           G H /     ],
      F => [ qw/               I J / ],
    );
    
    sub postorder {
      my($root,$hash) = @_;
      my @parents = @{ $parents{$root} || [] };
      postorder($_, $hash) for @parents;
      return if $sha1{$root};
      @parents = map "-p $sha1{$_}", @parents;
      chomp($sha1{$root} = `git commit-tree @parents -m "$root" $hash`);
      die "$0: git commit-tree failed" if $?;
      system("git tag -a -m '$sha1{$root}' '$root' '$sha1{$root}'") == 0 or die "$0: git tag failed";
    }
    
    $0 =~ s!^.*/!!;  # / fix Stack Overflow highlighting
    my $repo = mkdtemp "repoXXXXXXXX";
    chdir $repo or die "$0: chdir: $!";
    system("git init") == 0               or die "$0: git init failed";
    chomp(my $tree = `git write-tree`);      die "$0: git write-tree failed" if $?;
    
    postorder 'A', $tree;
    system "git update-ref HEAD   $sha1{A}"; die "$0: git update-ref failed" if $?;
    system "git update-ref master $sha1{A}"; die "$0: git update-ref failed" if $?;
    
    # for browsing history - http://blog.kfish.org/2010/04/git-lola.html
    system "git config alias.lol  'log --graph --decorate --pretty=oneline --abbrev-commit'";
    system "git config alias.lola 'log --graph --decorate --pretty=oneline --abbrev-commit --all'";
    
    它仅在 git lol and git lola 的新的一次性仓库中添加了别名,因此您可以按以下方式查看历史记录:
    $ git lol
    *   29392c8 (HEAD -> master, tag: A) A
    |\
    | * a1ef6fd (tag: C) C
    | |
    |  \
    *-. \   8ae20e9 (tag: B) B
    |\ \ \
    | | |/
    | | *   03160db (tag: F) F
    | | |\
    | | | * 9df28cb (tag: J) J
    | | * 2afd329 (tag: I) I
    | * a77cb1f (tag: E) E
    *   cd75703 (tag: D) D
    |\
    | * 3043d25 (tag: H) H
    * 4ab0473 (tag: G) G
    
    请注意,在您的计算机上,SHA-1对象名称与上面的名称不同,但是标记允许您按名称寻址提交并检查您的理解。
    $ git log -1 --format=%f $(git rev-parse A^)
    B
    $ git log -1 --format=%f $(git rev-parse A~^3~)
    I
    $ git log -1 --format=%f $(git rev-parse A^2~)
    F
    
    “Specifying Revisions” in the git rev-parse documentation充满了重要信息,值得深入阅读。另请参见Git Tools - Revision Selection书中的Pro Git
    家长提交顺序
    git自己的历史记录中的89e4fcb0dd提交是 merge 提交,因为git show 89e4fcb0dd用Merge header 行表示,该行显示了直接祖先的对象名称。

    我们可以通过要求git rev-parse依次显示89e4fcb0dd的直系 parent 来确认订购。
    $ git rev-parse 89e4fcb0dd^1 89e4fcb0dd^2 89e4fcb0dd^3
    c670b1f876521c9f7cd40184bf7ed05aad843433
    649bf3a42f344e71b1b5a7f562576f911a1f7423
    b67d40adbbaf4f5c4898001bf062a9fd67e43368
    
    查询不存在的第四父级将导致错误。
    $ git rev-parse 89e4fcb0dd^4
    89e4fcb0dd^4
    fatal: ambiguous argument '89e4fcb0dd^4': unknown revision or path not in the working tree.
    Use '--' to separate paths from revisions, like this:
    'git <command> [<revision>...] -- [<file>...]'
    
    如果只想提取 parent ,则使用pretty format %P表示完整的散列
    $ git log -1 --pretty=%P 89e4fcb0dd
    c670b1f876521c9f7cd40184bf7ed05aad843433 649bf3a42f344e71b1b5a7f562576f911a1f7423 b67d40adbbaf4f5c4898001bf062a9fd67e43368
    
    或缩写 parent 的%p
    $ git log -1 --pretty=%p 89e4fcb0dd
    c670b1f876 649bf3a42f b67d40adbb
    

    07-24 09:37
    查看更多