[git] Git에서 HEAD ^와 HEAD ~의 차이점은 무엇입니까?

힘내에서 개체를 커밋 할 때 내가 조상을 지정, 나는 사이에 혼동하고있어 HEAD^HEAD~.

둘 다 같은 “번호”버전이 HEAD^3HEAD~2.

그들은 나에게 매우 유사하거나 똑같아 보이지만 물결표와 캐럿 사이에 차이점이 있습니까?



답변

엄지 손가락의 규칙

  • ~대부분의 시간을 사용 하여 여러 세대 (일반적으로 원하는 것)로 되돌아갑니다.
  • ^병합 커밋에 사용 -둘 이상의 (즉시) 부모가 있기 때문에

기억술:

  • 물결 ~모양은 거의 선형이며 직선으로 뒤로 가고 싶습니다.
  • 캐럿 ^은 도로에서 나무 나 포크의 흥미로운 부분을 제안합니다

틸데

의 “지정 개정”섹션 git rev-parse문서 를 정의 ~

<rev>~<n>master~3
접미사 ~<n>개정 파라미터는이 오브젝트 저지 수단 인 N 번째 지정된 발생 조상 만 시조 따라 오브젝트를 저지한다. 예를 들어, <rev>~3동등 <rev>^^^동등하다 <rev>^1^1^1

뿐만 아니라 모든 커밋의 부모에게 갈 수 있습니다 HEAD. 예를 들어, master~2마스터 커밋 팁의 조부모를 의미하며 병합 커밋에서 첫 번째 부모를 선호합니다.

탈자 부호

Git 히스토리는 비선형 : DAG (Directed Acyclic Graph) 또는 트리입니다. A에 대한 하나의 부모 커밋 rev~rev^같은 일을 의미한다. 캐럿 선택기는 병합 커밋에 유용하게 사용됩니다. 각 커밋은 둘 이상의 부모의 자식이므로 생물학에서 빌려온 언어에 부담을주기 때문입니다.

HEAD^현재 지점 끝의 첫 번째 직계 부모를 의미합니다 . HEAD^의 줄임말이며 적절하게 HEAD^1주소를 지정할 수도 있습니다 HEAD^2. 문서동일한 섹션에서 다음git rev-parse 과 같이 정의합니다.

<rev>^, 예를 들면 HEAD^ ,v1.5.1^0
접미사 ^개정 파라미터는 객체 커밋의 제 부모를 의미한다. ^<n>수단 N 번째 상위 ([ ]은 <rev>^동일하다 <rev>^1). 특수 규칙으로, <rev>^0커밋 자체를 의미하며 커밋 <rev>객체를 참조하는 태그 객체의 객체 이름 이 사용될 때 사용됩니다 .

이 지정자 또는 선택기가 임의로 체인 할 수 있습니다 예를 들어 , topic~3^2영어 병합의 두 번째 부모가에 그 (삼대 다시) 지점의 현재 팁의 증조 할아버지 커밋 topic.

의 전술 섹션 git rev-parse문서는 개념적인 자식의 역사를 통해 많은 경로를 추적합니다. 시간은 일반적으로 아래쪽으로 흐릅니다. 커밋 D, F, B 및 A는 병합 커밋입니다.

다음은 Jon Loeliger의 그림입니다. 커밋 노드 B와 C는 모두 커밋 노드 A의 부모입니다. 부모 커밋은 왼쪽에서 오른쪽으로 정렬됩니다.

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A

A =      = A^0
B = A^   = A^1     = A~1
C = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2

아래 코드를 실행하여 인용 된 그림과 히스토리가있는 자식 저장소를 만듭니다.

#! /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 lolgit 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

에서 “지정 개정” git rev-parse문서는 좋은 정보가 가득과 가치에 대한 깊이있는 읽기입니다. Pro Git 서적에서 Git Tools-Revision Selection 을 참조하십시오 .

학부모 커밋 순서

git 자신의 히스토리에서 커밋 89e4fcb0dd 는 머지 커밋으로, git show 89e4fcb0dd직접적인 조상의 객체 이름을 표시하는 Merge 헤더 행을 나타냅니다.

commit 89e4fcb0dd01b42e82b8f27f9a575111a26844df
Merge: c670b1f876 649bf3a42f b67d40adbb
Author: Junio C Hamano <gitster@pobox.com>
Date:   Mon Oct 29 10:15:31 2018 +0900

    Merge branches 'bp/reset-quiet' and 'js/mingw-http-ssl' into nd/config-split […]

git rev-parse89e4fcb0dd의 직계 부모를 순서대로 보여 달라고 요청하여 주문을 확인할 수 있습니다 .

$ 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>...]'

부모 만 추출 하려면 전체 해시에 예쁜 형식 %P 을 사용하십시오.

$ git log -1 --pretty=%P 89e4fcb0dd
c670b1f876521c9f7cd40184bf7ed05aad843433 649bf3a42f344e71b1b5a7f562576f911a1f7423 b67d40adbbaf4f5c4898001bf062a9fd67e43368

또는 %p약식 부모의 경우.

$ git log -1 --pretty=%p 89e4fcb0dd
c670b1f876 649bf3a42f b67d40adbb


답변

차이 HEAD^HEAD~웰 (존 Loeliger 의해) 션에 의해 설명된다 발견 http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html .

이 문서는 초보자에게는 다소 모호 할 수 있으므로 아래 그림을 재현했습니다.

G   H   I   J
 \ /     \ /
  D   E   F
   \  |  / \
    \ | /   |
     \|/    |
      B     C
       \   /
        \ /
         A
A =      = A^0
B = A^   = A^1     = A~1
C = A^2
D = A^^  = A^1^1   = A~2
E = B^2  = A^^2
F = B^3  = A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2  = B^^2    = A^^^2  = A~2^2
I = F^   = B^3^    = A^^3^
J = F^2  = B^3^2   = A^^3^2


답변

모두 ~^자신에 커밋의 부모를 참조 ( ~~^^조부모 등, 커밋에 모두 참조) 그러나 그들이이 숫자와 함께 사용될 때 의미에서 차이 :

  • ~2커밋에 둘 이상의 부모가있는 경우 첫 번째 부모를 통해 계층 구조에서 두 수준을 의미 합니다.

  • ^2커밋에 둘 이상의 부모 가있는 두 번째 부모를 의미 합니다 (즉 병합이기 때문에)

그래서 이들은, 결합 될 수 HEAD~2^3수단 HEAD의 조부모의 세 번째 부모가 커밋 커밋.


답변

내 두 센트 …

여기에 이미지 설명을 입력하십시오


답변

다음은 http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde 에서 간단하게 설명한 좋은 설명입니다 .

ref~약식이며 ref~1커밋의 첫 번째 부모를 의미합니다. ref~2커밋의 첫 번째 부모의 첫 번째 부모를 의미합니다. ref~3커밋의 첫 번째 부모의 첫 번째 부모의 첫 번째 부모를 의미합니다. 등등.

ref^약식이며 ref^1커밋의 첫 번째 부모를 의미합니다. 그러나 둘이 다른 점은 ref^2커밋의 두 번째 부모 를 의미한다는 것입니다 (커밋은 병합 될 때 커밋이 두 부모를 가질 수 있음을 기억하십시오).

^~연산자는 결합 할 수 있습니다.

여기에 이미지 설명을 입력하십시오


답변

^<n>형식을 사용하면 커밋의 n 번째 부모 (병합과 관련됨)를 선택할 수 있습니다. 이 ~<n>형식을 사용하면 항상 첫 번째 상위를 따르는 n 번째 상위 커밋을 선택할 수 있습니다. 몇 가지 예는 git-rev-parse 설명서를 참조하십시오 .


답변

git은 “from-where-you-come”/ “want-to-go-back-now”를 추적하기위한 구문을 가지고 있음을 주목할 가치가 있습니다. 예를 들어, HEAD@{1}새로운 커밋 위치로 점프 한 곳을 참조 할 것입니다.

기본적으로 HEAD@{}변수는 HEAD 이동 히스토리를 캡처하며 명령을 사용하여 git의 참조를 조사하여 특정 헤드를 사용하도록 결정할 수 있습니다 git reflog.

예:

0aee51f HEAD@{0}: reset: moving to HEAD@{5}
290e035 HEAD@{1}: reset: moving to HEAD@{7}
0aee51f HEAD@{2}: reset: moving to HEAD@{3}
290e035 HEAD@{3}: reset: moving to HEAD@{3}
9e77426 HEAD@{4}: reset: moving to HEAD@{3}
290e035 HEAD@{5}: reset: moving to HEAD@{3}
0aee51f HEAD@{6}: reset: moving to HEAD@{3}
290e035 HEAD@{7}: reset: moving to HEAD@{3}
9e77426 HEAD@{8}: reset: moving to HEAD@{3}
290e035 HEAD@{9}: reset: moving to HEAD@{1}
0aee51f HEAD@{10}: reset: moving to HEAD@{4}
290e035 HEAD@{11}: reset: moving to HEAD^
9e77426 HEAD@{12}: reset: moving to HEAD^
eb48179 HEAD@{13}: reset: moving to HEAD~
f916d93 HEAD@{14}: reset: moving to HEAD~
0aee51f HEAD@{15}: reset: moving to HEAD@{5}
f19fd9b HEAD@{16}: reset: moving to HEAD~1
290e035 HEAD@{17}: reset: moving to HEAD~2
eb48179 HEAD@{18}: reset: moving to HEAD~2
0aee51f HEAD@{19}: reset: moving to HEAD@{5}
eb48179 HEAD@{20}: reset: moving to HEAD~2
0aee51f HEAD@{21}: reset: moving to HEAD@{1}
f916d93 HEAD@{22}: reset: moving to HEAD@{1}
0aee51f HEAD@{23}: reset: moving to HEAD@{1}
f916d93 HEAD@{24}: reset: moving to HEAD^
0aee51f HEAD@{25}: commit (amend): 3rd commmit
35a7332 HEAD@{26}: checkout: moving from temp2_new_br to temp2_new_br
35a7332 HEAD@{27}: commit (amend): 3rd commmit
72c0be8 HEAD@{28}: commit (amend): 3rd commmit

예를 들어 로컬 커밋 a-> b-> c-> d를 수행 한 다음 코드를 확인하기 위해 2 개의 커밋을 버리고 git reset HEAD~2다시 HEAD를 d-로 옮기고 싶습니다 git reset HEAD@{1}.