[解決済み] GitのHEAD^とHEAD~の違いは何ですか?
質問
Git で祖先のコミット・オブジェクトを指定する際、以下のように混乱します。
HEAD^
と
HEAD~
.
どちらも、以下のような番号付きバージョンです。
HEAD^3
と
HEAD~2
.
私にはとても似ているというか、同じに見えるのですが、チルダとキャレットの違いはあるのでしょうか?
どのように解決するのですか?
経験則
-
使用方法
~
ほとんどの場合、何世代もさかのぼることができます。 -
使用する
^
マージコミットの場合 - 2つ以上の (直接の) 親を持つため
ニーモニック
-
ティルデ
~
は、見た目はほぼ直線的で、まっすぐ後方に進みたがる -
キャレット
^
分岐点
ティルデ
は
"リビジョンの指定 "セクションの
git rev-parse
ドキュメント
が定義する
~
として
<rev>~<n>
, 例.master~3
接尾語~<n>
をリビジョンパラメータに指定すると、そのコミットオブジェクトが n th 指定されたコミットオブジェクトの世代の先祖で、最初の親にのみ続く。例えば<rev>~3
は、次のものと同等です。<rev>^^^
と等価である。<rev>^1^1^1
...
に限らず、あらゆるコミットの親を取得することができます。
HEAD
. また、世代を遡ることもできます:例えば
master~2
は master ブランチの先端の祖父母を意味し、マージコミットでは最初の親が優先されます。
キャレット
Git の歴史は非線形です。有向無サイクル・グラフ (DAG) あるいはツリーです。親が一人しかいないコミットの場合
rev~
と
rev^
は同じものを意味します。キャレットセレクターはマージコミットにおいて有用です。なぜなら、マージコミットはそれぞれが2つ以上の親の子であり、生物学から借用した言語を用いているからです。
HEAD^
は、最初の
即時
現在のブランチの先端の親
HEAD^
は
HEAD^1
というアドレスも可能です。
HEAD^2
などを適宜選択してください。その
と同じセクションを
git rev-parse
ドキュメント
は、次のように定義しています。
<rev>^
, などHEAD^
,v1.5.1^0
接尾語^
のリビジョンパラメーターは、そのコミットオブジェクトの最初の親を意味します。^<n>
は n th 親([. 例 ]<rev>^
は、次のものと同等です。<rev>^1
). 特別なルールとして<rev>^0
はコミットそのものを意味し、以下のような場合に使用されます。<rev>
は、コミットオブジェクトを参照するタグオブジェクトのオブジェクト名です。
使用例
これらの指定子やセレクタは、任意に連鎖させることができる。
例
,
topic~3^2
は、ブランチの現在の先端の曽祖父母 (3世代前) にあたるマージコミットの2番目の親です。
topic
.
は
の前述したセクションは
git rev-parse
ドキュメント
は、想定されるgitの履歴の多くのパスをトレースします。時間はおおむね下向きに流れます。コミット D、F、B、A はマージコミットです。
Jon Loeligerによる図解です。コミットノード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
以下のコードを実行すると、履歴が引用した図と一致する 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
と
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
は
の「リビジョンを指定する」。
git rev-parse
ドキュメンテーション
は素晴らしい情報が満載で、深く読み込む価値があります。以下もご参照ください。
Git ツール - リビジョン選択
書籍より
プロGit
.
親コミットの順番
コミット
89e4fcb0dd
はマージコミットです。
git show 89e4fcb0dd
は、直前の先祖のオブジェクト名を表示する Merge ヘッダー行で示されます。
commit 89e4fcb0dd01b42e82b8f27f9a575111a26844df
Merge: c670b1f876 649bf3a42f b67d40adbb
Author: Junio C Hamano <[email protected]>
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
存在しない第4の親を問い合わせると、エラーになります。
$ 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
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] git pull」と「git fetch」の違いは何ですか?
-
[解決済み] 現在のGit作業ツリーからローカル(未追跡)ファイルを削除する方法
-
[解決済み] git rebase の取り消し
-
[解決済み] Git のリモートブランチを作成する方法を教えてください。
-
[解決済み] git add -A」と「git add .」の違い。
-
[解決済み] .gitignoreと.gitkeepの違いは何ですか?
-
[解決済み] Git のコミットで変更点を確認するには?
-
[解決済み] Git で最新のコミットを新しいブランチに移動する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】gpgがデータの署名に失敗した fatal: failed to write commit object [Git 2.10.0].
-
[解決済み] 複数のgitコミットを元に戻すには?
-
[解決済み] TortoiseGitで「git did not exit cleanly (exit code 128)」というエラーを解決するには?[クローズド]
-
[解決済み] git rebase: "error: cannot stat 'file': パーミッションが拒否されました"
-
[解決済み] GitのFETCH_HEADとはどういう意味ですか?
-
[解決済み] ssh-keygen' は内部コマンドまたは外部コマンドとして認識されません。
-
[解決済み] git commitの代わりに行った "git commit --amend "を元に戻すには?
-
[解決済み] Git のコミットを「取り消す」方法を教えてください。
-
[解決済み] コミット間の差分表示
-
[解決済み] ある範囲のコミットを選んで、別のブランチにマージする方法は?