Git에서 HEAD^와 HEAD~의 차이점은 무엇입니까?
Git에서 조상 커밋 개체를 지정하면 다음과 같이 혼동됩니다.HEAD^
그리고.HEAD~
.
둘 다 다음과 같은 "번호가 지정된" 버전을 가지고 있습니다.HEAD^3
그리고.HEAD~2
.
저랑 많이 비슷하거나 비슷한 것 같은데, 타일과 캐럿의 차이점이 있나요?
경험칙
- 사용하다
~
대부분의 경우 - 여러 세대로 거슬러 올라가며, 일반적으로 원하는 것. - 사용하다
^
커밋 - 두부모가 에 - - 의상부있때기문커다니입.
니모닉:
- 데
~
로 한 로 가고 . - 럿
^
합니다.
틸데
설명서의 "개정사항 지정" 섹션은 다음을 정의합니다.~
~하듯이
<rev>~<n>
를 들어, 예를 들어, 기호입니다.master~3
~<n>
revision 매개 변수에 대한 명령은 첫 번째 부모만 따르는 명명된 커밋 개체의 다음 세대th 조상인 커밋 개체를 의미합니다.예를들면,<rev>~3
는 와동합다니등다에 합니다.<rev>^^^
는 와동한등에 합니다.<rev>^1^1^1
…
은 단순히 약속이든 할 수 .HEAD
다음과 같이 세대를 통해 다시 이동할 수도 있습니다. 예를 들어,master~2
병합 커밋 시 첫 번째 부모를 선호하는 마스터 분기 팁의 조부모를 의미합니다.
캐럿
Git 이력은 비선형적입니다. DAG(방향 비순환 그래프) 또는 트리입니다.의 경우 부가한 있명커 경의 우밋는 ▁for 경우의커rev~
그리고.rev^
같은 뜻입니다.캐럿 선택기는 병합 커밋에서 유용하게 사용됩니다. 각 커밋은 두 명 이상의 부모의 자식이며 생물학에서 차용한 언어를 변형시키기 때문입니다.
HEAD^
현재 분기 팁의 첫 번째 직접 상위 항목을 의미합니다. HEAD^
는 의줄말임의 줄임말입니다.HEAD^1
그리고 당신은 또한 주소를 쓸 수 있습니다.HEAD^2
필요에 따라 기타 작업을 참조.설명서의 동일한 섹션에서는 다음과 같이 정의합니다.
<rev>^
예를 들면HEAD^
,v1.5.1^0
^
의 첫 합니다.^<n>
다음 부모를th 의미합니다([예:]).<rev>^
는 와동합다니등다에 합니다.<rev>^1
). ). 특별한 규칙으로,<rev>^0
커밋 자체를 의미하며 다음과 같은 경우에 사용됩니다.<rev>
커밋 개체를 참조하는 태그 개체의 개체 이름입니다.
예
이러한 지정자 또는 선택자는 임의로 체인될 수 있습니다. 예를 들어,topic~3^2
의 현재 전의 두 입니다.topic
.
앞서 설명한 설명서의 섹션에서는 개념적 깃 이력을 통해 많은 경로를 추적합니다.시간은 일반적으로 아래로 흐릅니다.커밋 D, F, B 및 A는 병합 커밋입니다.
여기 존 뢰리거의 삽화가 있습니다.커밋 노드 B와 C는 모두 커밋 노드 A의 상위 노드입니다.오른쪽으로 (. 위밋커오정다니렬됩로으. (N.B.) 그
git log --graph
명령은 기록을 반대 순서로 표시합니다.)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 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
설명서의 "개정사항 지정"은 훌륭한 정보로 가득 차 있으며 자세히 읽을 가치가 있습니다.Pro Git 책에서 Git 도구 - 개정 선택을 참조하십시오.
상위 커밋 순서
git 자체 이력에서 커밋 89e4fcb0dd는 병합 커밋입니다.git show 89e4fcb0dd
인접한 조상의 개체 이름을 표시하는 병합 헤더 행을 나타냅니다.
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-parse
.89e4fcb0dd의 부모는 다음과 같습니다.
$ 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>...]'
$ git log -1 --pretty=%P 89e4fcb0dd
c670b1f876521c9f7cd40184bf7ed05aad843433 649bf3a42f344e71b1b5a7f562576f911a1f7423 b67d40adbbaf4f5c4898001bf062a9fd67e43368
또는%p
약칭 부모를 위한.
$ git log -1 --pretty=%p 89e4fcb0dd
c670b1f876 649bf3a42f b67d40adbb
의 HEAD^
그리고.HEAD~
는 http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html 에서 볼 수 있는 (Jon Loeliger의) 그림에 잘 설명되어 있습니다.
이 설명서는 초보자에게 다소 모호할 수 있으므로 아래 그림을 재현했습니다.
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
의 조부모 커밋의 세 번째 부모 커밋.
내 2센트...
다음은 http://www.paulboxley.com/blog/2011/06/git-caret-and-tilde 에서 발췌한 매우 좋은 설명입니다.
ref~
는 의줄입니다말의 줄임말입니다.ref~1
위원회의 첫 번째 부모를 의미합니다.ref~2
커밋의 첫 번째 부모를 의미합니다.ref~3
커밋의 첫 번째 부모 첫 번째 부모를 의미합니다.등등.
ref^
는 의줄입니다말의 줄임말입니다.ref^1
위원회의 첫 번째 부모를 의미합니다.하지만 둘이 다른 점은ref^2
커밋의 두 번째 부모를 의미합니다(따라서 커밋은 병합될 때 두 개의 부모를 가질 수 있습니다).그
^
그리고.~
연산자를 결합할 수 있습니다.
간단히 말해:
~
조상지를 지정합니다.^
parents 을 합니다.
병합할 때 하나 이상의 분기를 지정할 수 있습니다.그러면 커밋에는 두 명 이상의 부모가 있고 그 다음에는^
부모를 나타내는 데 유용합니다.
A 지점에 있고 B 지점과 C 지점이 두 개 더 있다고 가정합니다.
각 분기에서 마지막 3개 커밋은 다음과 같습니다.
- A: A1, A2, A3
- B: B1, B2, B3
- C: C1, C3, C3
이제 분기 A에서 다음 명령을 실행합니다.
git merge B C
그런 다음 세 개의 분기를 함께 결합합니다(여기서 병합 커밋에는 세 개의 부모가 있음).
그리고.
~
첫 번째 분기의 n번째 조상을 나타냅니다.
HEAD~
A3를 나타냄HEAD~2
A2를 나타냄HEAD~3
A1을 나타냄
^
부모가 아님을 나타냅니다.
HEAD^
A3를 나타냄HEAD^2
B3를 나타냄HEAD^3
C3를 나타냅니다.
의 다음 ~
또는^
서로 옆에 있는 것은 이전 캐릭터가 지정한 커밋의 맥락입니다.
공지사항 1:
HEAD~3
다음과.HEAD~~~
대상:HEAD^^^
(매번 A1 표시),
그리고 일반적으로:
HEAD~n
다음과.HEAD~...~
(n회)~
및 ) 및대상:HEAD^...^
(n회)^
).
공지사항 2:
HEAD^3
와 동일하지 않습니다.HEAD^^^
(첫 번째는 C3을 나타내고 두 번째는 A1을 나타냅니다.)
그리고 일반적으로:
HEAD^1
는 와동합다니와 .HEAD^
,- 그러나 n > 1의 경우:
HEAD^n
와 항상 같지는 않습니다.HEAD^...^
(n회)^
).
그^<n>
format을 사용하여 커밋의 n번째 상위 항목(병합 포함)을 선택할 수 있습니다. 그~<n>
format을 사용하면 항상 첫 번째 부모를 따라 n번째 조상 커밋을 선택할 수 있습니다.몇 가지 예는 git-rev-parse의 설명서를 참조하십시오.
에는 " git는를예를들어에다기니추있하위 "from-where-you-come"/"want-to-go-back-now")를도 있다는 점에 주목할 필요가 있습니다.HEAD@{1}
새 커밋 위치로 점프한 위치를 참조합니다.
으로 기적으로.HEAD@{}
변수는 HEAD 이동 기록을 캡처하며, 명령을 사용하여 git의 reflog를 조사하여 특정 헤드를 사용할지 결정할 수 있습니다.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
그 다음엔 머리를 다시 d로 돌리고 싶어요git reset HEAD@{1}
.
HEAD~와 HEAD^의 차이에 대한 실제 예:
TLDR
대부분의 경우 원하는 것입니다. 현재 분기에 대한 과거 커밋을 참조합니다.
상위 항목 참조(git-interval은 두 번째 상위 항목 이상을 생성함)
A^A~와 .
A, 따라서 A~~~는 A^^와 같습니다.
는 A A~2는 A^2입니다.
2의 이기 때문입니다.
^2는 어떤 것의 줄임말이 아니지만, 그것은 두 번째 부모를 의미합니다.
HEAD^^^
는 와동합다니와 .HEAD~3
HEADHEAD 에 세
HEAD^2
의 두 합니다.
HEAD~는 "지점"의 첫 번째 부모를 지정합니다.
HEAD^를 사용하면 커밋의 특정 상위 항목을 선택할 수 있습니다.
예:
곁가지를 따라가려면 다음과 같은 것을 지정해야 합니다.
master~209^2~15
OP: Git에서 조상 커밋 개체를 지정하면 HEAD^와 HEAD~가 혼동됩니다.
Git에서 HEAD^와 HEAD~의 차이점은 무엇입니까?
의 HEAD^
및 () »HEAD~
인데, 이 (틸데)라는 특정한 경우에는 역사를 뒤로 이동합니다.HEAD
.
틸데~
<rev>~[<n>]
<n>th
번째* 부모님만 , * 릅니다따상조.
캐럿 ^
<rev>^[<n>]
<n>th
조상의 1세대 조상의
*첫 번째 상위 항목은 항상 병합의 왼쪽에 있습니다(예: 병합된 분기의 커밋).
~ 및 ^ 함께 가입
아래 그림에서 볼 수 있듯이 두 셀렉터 ~와 ^를 함께 사용할 수 있습니다.또한 를 사용하는 대신HEAD
시작점으로 분기, 태그 또는 커밋 해시와 같은 모든 일반 참조를 사용할 수 있습니다.
또한 선택하고자 하는 조상에 따라 아래 표와 같이 ^과 ~를 서로 바꾸어 사용할 수 있습니다.
출처: 이 주제에 대한 자세한 내용은 이 블로그 게시물에서 확인할 수 있습니다.
BRANCH
git checkout HEAD^2
선택한 분기로 이동하여 커밋의 두 번째 분기를 선택합니다(커밋 트리에서 한 단계 뒤로 이동).
COMMIT
HEAD~2git checkout HEAD~2개
branch에서 2 커밋을 합니다.
~ 및 ^ 상대 참조를 모두 부모 선택기로 정의하는 것은 공식 Git Book을 포함하여 지금까지 인터넷에서 발표된 모든 곳에서 지배적인 정의입니다.네, 그들은 부모 선택자이지만, 이 "설명"의 문제는 우리의 목표인 두 가지를 어떻게 구별하느냐에 완전히 어긋난다는 것입니다.:)
또 다른 문제는 COMMIT 선택(일명 HEAD^ === HEAD~)에 ^ BRANCH 선택기를 사용하도록 권장되는 경우입니다.
다시 말하지만, 네, 이런 식으로 사용할 수는 있지만, 이것은 설계된 목적이 아닙니다.^ 분기 선택기의 역방향 이동 동작은 그 목적이 아닌 부작용입니다.
병합된 커밋에서만 ^ BRANCH 선택기에 번호를 할당할 수 있습니다.따라서 분기 중에서 선택해야 하는 경우에만 전체 용량을 사용할 수 있습니다.그리고 포크로 선택 항목을 표현하는 가장 간단한 방법은 선택한 경로/분기로 이동하는 것입니다. 이는 커밋 트리에서 한 단계 뒤로 이동하는 것입니다.그것은 단지 부작용일 뿐, 주된 목적은 아닙니다.
~
부모를 의미합니다.
^
병합 커밋과 같이 두 개 이상의 부모가 있는 경우.두 번째 부모 또는 다른 부모 중 하나를 선택할 수 있습니다.
따라서 (HEAD~ 또는 HEAD^)와 같은 것 하나만 있어도 같은 결과를 얻을 수 있습니다.
입력할지 여부를 고민하는 경우HEAD^
또는HEAD~
명령에서 다음 중 하나를 사용합니다.
둘 다 현재 커밋의 첫 번째 부모인 동일한 커밋의 이름입니다.
로 마가지로찬.master~
그리고.master^
두 이름 모두 마스터의 첫 번째 부모 이름입니다.
와 같은 으로.2 + 2
그리고.2 x 2
둘 다입니다4
그들은 그곳에 가는 방법이 다르지만, 답은 같습니다.
다음과 같은 질문에 답합니다.Git에서 HEAD^와 HEAD~의 차이점은 무엇입니까?
병합을 방금 했거나(따라서 현재 커밋에 두 개 이상의 부모가 있음) 캐럿과 타일이 작동하는 방식에 여전히 관심이 있는 경우 다른 답변(여기서는 복제하지 않음)과 반복적으로 사용하는 방법(예:HEAD~~~
) 또는숫예자예()로 HEAD^2
, 이으로 시간을 할 수 있기를 그렇지 않으면 이 답변으로 시간을 절약할 수 있기를 바랍니다.
간단히 말해서, 첫 번째 수준의 부모(조상, 상속, 혈통 등) HEAD^ 및 HEAD~는 모두 HEAD(커밋) 위에 하나의 부모(위치)가 있는 동일한 커밋을 가리킵니다.
또한 HEAD^ = HEAD^1 = HEAD~ = HEAD~1.그런데 HEAD^^!=HEAD^2!=HEAD~2.아직 HEAD^^ =HEAD~2.계속 읽어보세요.
상위 계층의 첫 번째 수준을 넘어서면 특히 작업 분기/마스터 분기가 (다른 분기에서) 병합된 경우 상황이 더 까다로워집니다.캐럿인 HEAD^^ =HEAD~2(동등함)와 구문 문제도 있지만 HEAD=!^^HEAD^2(전혀 다른 두 가지)입니다.
각/캐럿은 HEAD의 첫 번째 부모를 나타냅니다. 따라서 함께 문자열로 묶인 캐럿은 연결된 캐럿의 수 또는 타일 뒤에 오는 숫자(둘 다 동일한 의미)를 기준으로 첫 번째 부모(첫 번째 부모)의 첫 번째 부모 등을 엄격하게 참조하기 때문입니다.첫 번째 부모와 함께 지내며 x세대로 올라갑니다.
HEAD~2(또는 HEAD^^)는 계층 구조에서 현재 커밋(HEAD) 위/위에 있는 두 단계의 조상인 커밋을 의미하며, HEAD의 조부모 커밋을 의미합니다.
반면 HEAD^2는 첫 번째 부모의 두 번째 부모의 커밋이 아니라 두 번째 부모의 커밋을 의미합니다.이는 캐럿이 커밋의 부모를 의미하고, 뒤에 오는 숫자는 어떤 부모 커밋을 참조하는지를 의미하기 때문입니다(캐럿이 숫자 뒤에 숫자가 붙지 않는 경우에는 [1, 첫 번째 부모를 의미하기 때문에].캐럿과 달리 뒤에 오는 숫자는 계층이 위쪽으로 올라가는 또 다른 수준을 의미하는 것이 아니라 계층에 있는 올바른 부모(커밋)를 찾아야 하는 측면의 수준 수를 의미합니다.타일드 식의 숫자와는 달리 캐럿을 진행하는 숫자(즉시)에 관계없이 계층 구조에서 상위 한 개의 부모만 됩니다.캐럿의 후행 번호는 계층 전반에 걸쳐 부모(연속 케어 횟수와 동일한 상위 부모 수준)에 대해 옆으로 계산됩니다.
따라서 HEAD^3은 HEAD 커밋의 세 번째 부모와 동일합니다(HEAD^^^ 및 HEAD~3은 증조부모가 아닙니다...).
언급URL : https://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git
'programing' 카테고리의 다른 글
UI 테스트 실패 - 요소 또는 하위 요소 모두 보안에 중점을 두지 않음텍스트 필드 (0) | 2023.05.24 |
---|---|
Project-Swift.h를 Object-C 클래스로 가져오는 중...파일을 찾을 수 없음 (0) | 2023.05.24 |
스토리보드에서 간단한 둥근 단추를 만드는 방법은 무엇입니까? (0) | 2023.05.24 |
사용자 컨트롤의 데이터 컨텍스트 (0) | 2023.05.24 |
두 개의 개체 배열 병합 (0) | 2023.05.24 |