[解決済み] git rev-listを理解する
質問
git hookのサンプルを探しているときに、以下の投稿に出会いました。 https://github.com/Movidone/git-hooks/blob/master/pre-receive で、以下のコマンドを理解したいと思いました。
git rev-list $new_list --not --all
new_listの取得先。
NULL_SHA1="0000000000000000000000000000000000000000" # 40 0's
new_list=
any_deleted=false
while read oldsha newsha refname; do
case $oldsha,$newsha in
*,$NULL_SHA1) # it's a delete
any_deleted=true;;
$NULL_SHA1,*) # it's a create
new_list="$new_list $newsha";;
*,*) # it's an update
new_list="$new_list $newsha";;
esac
done
rev-listはコミットを時系列で逆順に表示するのだと思いました。
しかし、誰かもっと詳しく
-not
と
-all
のオプションは何のためにあるのでしょうか?
ドキュメントの通りです。
--not
Reverses the meaning of the ^ prefix (or lack thereof) for all following revision specifiers, up to the next --not.
--all
Pretend as if all the refs in refs/ are listed on the command line as <commit>.
これらのオプションを完全に理解することはできません。
[更新情報]
いくつかのテストコミットを行った後、もし私が
--not
と
--all
のオプションは、その後
git rev-list
は、ブランチ上のすべてのコミットをリストアップし、プッシュする予定のコミットはリストアップしません。
しかし、なぜ、以下のような場合に、ターミナルに sha の値が表示されないのかを理解したいと思います。
--all
オプションが渡されるのですか?
解決方法は?
その
git rev-list
コマンドは
非常に
複雑な
超中心
コマンドは、Git で何をするかというと
グラフを歩く
. この単語は
グラフ
は、コミットグラフそのものと、場合によってはその次のレベル (Gitオブジェクトの
から到達可能な
コミット)。
rev-listはコミットを時系列で逆順に表示するのだと思いました。
正確ではありませんが、近いです。
- 順番は変更可能です。 その デフォルト は逆時系列です。
-
デフォルトでは、いくつかのコミットをウォークしますが、その際に
rev-list
を使えば、ツリーやブロブオブジェクト、さらにはタグオブジェクトも含めて、より深く掘り下げることができます。 これは、以下のようなプログラムのためのものです。git fetch
とgit push
(を呼び出す)。git pack-objects
) とgit pack-objects
. この可能性はここでは完全に無視するつもりですが、少なくとも触れておくべきだと思います。????
そこで
デフォルト
は、いくつかのコミットを時系列で逆順にリストアップします。 を正確に指定することは重要ですが、少し厄介です。
どの部分
グラフの
git rev-list
を歩く。
一部
で
いくつかのコミット
.
しかし、誰かもっと詳しく教えてください
--not
と--all
のオプションは何のためにあるのでしょうか?
として
VonCノート
は、その
効果
では、受信側のリポジトリに新しく追加されたコミットをリストアップします。 これは、この
git rev-list
コマンドは
プリレシーブフック
. 一般に、この特定のフックの外では、有用なことは何も行いません。 このように、Gitにおけるフックの実行時環境は、少なくとも少しは特別であることが多いのです。 (これはpre-receiveフック以外にも言えることです。それぞれのフックの起動時のコンテキストについて考えなければなりません)。
についてもっと詳しく
--not --all
は
--all
オプションは、あなたがドキュメントから引用したとおりの働きをします。
にあるすべての参照は
refs/
がコマンドラインにリストアップされています.
ということは、これは同等のことをするわけです。
git for-each-ref refs
: 各参照をループします。 これにはブランチ名 (
master
または
main
,
develop
,
feature/tall
などがありますが、これらはすべて本当は
refs/heads/
)、タグ名(
v1.2
というのは、本当は
refs/tags/v1.2
)、リモートトラッキングの名前(
origin/develop
というのは、本当は
refs/remotes/origin/develop
) 、置換参照 (
refs/replace/
)、隠し場所(
refs/stash
)、bisection refs、Gerritを使っている場合はGerrit refs、など。 なお、この
はしません。
は reflog エントリをループします。
は
--not
プレフィクスは単純なブーリアン演算です。 gitrevisions の構文では、次のようになります。
gitrevisionsのドキュメント
-のような書き方ができます。
develop
という意味です。
から始めるように言っています。
develop
と逆算し
インクルード
これらのコミット
のようなものだけでなく
^develop
という意味です。
から始めるように言っています。
develop
と逆算し
除く
これらのコミット
. だから、もし私が書いたら
git rev-list feature1 feature2 ^main
Gitにコミットをウォークするよう依頼しています
から到達可能な
という名前で識別されるコミット
feature1
と
feature2
に、しかし
除く
で識別されるコミットから到達可能なコミット。
main
. の一般的な考え方については、(かなり) 詳しく説明します。
到達可能性
とグラフウォーキングを参照してください。
Gitのように考える
.
は
--not
演算子は事実上
^
をそれぞれの参照に追加します。
git rev-list --not feature1 feature2 ^main
は、いわば略語です。
git rev-list ^feature1 ^feature2 main
から到達可能なコミットのリストをウォークします。
main
のどちらかから到達可能なものは除外されます。
feature1
または
feature2
.
通常
すべて
でコミットを見つけることができます。
--all
Gitを普通に日常的に使っている場合。
と
は今のところ "detached HEAD" を持っていません-detached HEAD モードは正確には
異常
が、通常の作業方法とは異なります。
--all
オプションで
git rev-list
を含めるように指示します。
すべて
というのは、すべてのコミット
は
すべてのリファレンスから到達可能です。
1
そこで
--not --all
効果的に
は除外されます。
のすべてのコミットに対してです。 そのため
--not --all
に、任意の
git rev-list
を使用すると、コミットの一覧が表示されなくなることがあります。 出力は空っぽです。なぜ私たちは悩んだのでしょうか?
デタッチド HEAD モードで、いくつかの新しいコミットを行った場合-たとえば、対話的なリベースや競合するリベースの最中などに起こります-は
git rev-list HEAD --not --all
は、以下のようなコミットをリストアップします。
は
から到達可能な
HEAD
しかし
ない
をどのブランチ名からも削除することができます。 たとえばこのリベースでは、これまでにコピーしたコミットだけが対象となります。
つまり、quot;detached HEAD"モードは、一度だけ、以下のような場所になります。
git rev-list --not --all
は、コマンドラインから有用である可能性があります。 しかし、あなたが調べているような状況、つまり
プリレシーブフック
-コマンドラインではありません。
受信前フック
を使用する場合
git push
を使用してコミットを送信します。
への
あなた自身のGit、あなたのGitです。
- は、新しいオブジェクト (新しいコミットやブロブなど) を保持するための隔離領域をセットアップします。 1
- は、送信者が何を送信すべきかを決定するために、送信者と交渉します。
- これらのオブジェクトを受信する。
- のリストを受け取ります。 Refの更新要求 . これらの更新リクエストは、基本的には単に この名前にこのハッシュIDを持たせる . 2
実際に使用する前に している 要求されたアップデートのいずれかを、あなたのGit:
- リスト全体をpre-receiveフックに送ります。 このフックは "no"と言うことができ、その場合、プッシュ全体が拒否されます。
- OKと出たら、リストを1つずつupdateフックに送ります。 そのフックが "ok" と言ったら、更新を実行します。 フックが "no"と言ったら、Git はその更新を拒否し、他の更新を調べます。
- ステップ2ですべての更新が受理または拒否された後、受理されたリストを受信後フックに送ります。
ステップ2で何らかのrefに追加された、必要なオブジェクトは、隔離からGitのオブジェクト・データベースに移動されます。 拒否されたものは、そうではありません。
では、典型的な
git push
. 新しいコミット(複数可)とリクエストを取得します。
新しいブランチ名を作成します。
feature/short
または、新しいコミットとリクエストを取得します。
既存のブランチ名を更新
develop
新しいコミットを古いコミットと一緒に含めるように
.
上記のステップ1では、新しいハッシュIDは1つです。 すべての参照名とその現在のハッシュIDおよび提案された新しいハッシュIDを読み込むループを実行しましたが、ループは一度だけしか実行されませんでした。
名前
されていた
git push
-された。 そのハッシュIDは
新しい
このコミットは、既存のブランチに追加されるか、あるいは新しいブランチ専用の tip やその他のコミットとなります。
次に
検査
これらのコミットは、既存のブランチから到達可能な既存のコミットとは関係ありません。 シンプルにするために
$new_list
では、新しいハッシュIDを1つだけと仮定してみましょう。
$new
と、ブランチ名には旧ハッシュIDを使用します。
$old
ブランチがすべて新しい場合は all-zeros となり、既存のブランチ名である場合は有効な既存のコミットとなります。
新しいコミットが完全に新しいブランチにある場合。
git rev-list $new ^master ^develop ^feature/short ^feature/tall
は、たとえば、既存のブランチがこの4つだけだとわかっている場合、それらをカバーします (そして、心配するようなタグなどがない場合)。 しかし、例えば、これらのブランチが追加される場合はどうでしょう。
develop
? というコミットは除外したい。
現在
にあります。
develop
. 私たちは
$old
のハッシュIDで行います。
git rev-list $new ^master ^$old ^feature/short ^feature/tall
を実行している人の新しいコミットだけがリストアップされます。
git push origin develop
に追加したい。
develop
.
しかし、考えてみてください。
$old
. これはハッシュIDです。 Gitはどこでそれを手に入れたのでしょうか? Git
ゲット
このハッシュIDは
名前
develop
. これは
プリレシーブフック
は
名前
develop
はまだ更新されていません
. そのため、名前
develop
は
古いハッシュIDに対応する名前
$old
. ということです。
git rev-list $new ^master ^develop ^feature/short ^feature/tall
意志 また を実行します。
もし
git rev-list $new
の後に "and not all existing" が続くと、仕事ができるようになります。
git rev-list $new --not --branches
が仕事をすることになります。 ここにあるのはほとんどそれです
を使用した場合の不具合は
--branches
は、タグや他の参照先を取得しないことです。 そこで
--not --branches --tags
しかし
--not --all
の方が短く、他の参照もすべて取得できます。
ということで、ここは
--not --all
は、受信前フックという特殊なケースに依存する。 を実行している人が提案する、新しいハッシュIDをリストアップします。
git push
は、Git が行のリストとして私たちに渡してきたものです。 私たちは
git rev-list
は、更新予定のコミットグラフを歩き、隔離領域にある新しいコミットを調べますが、すでにリポジトリにあるすべてのコミットは除外されます。 rev-list コマンドは一行ごとにハッシュ ID を生成し、それをシェルループで読み込んで以下のような処理を行います。
検査する
のコミットです。
1 隔離領域はGit 2.11で新たに導入されたものです。それ以前は、新しいオブジェクトはプッシュが拒否されてもしばらくはリポジトリに残っていることがありました。 隔離領域は、ほとんどの人にとってはそれほど大きな問題ではありませんが、GitHub のような大きなサーバーでは ロット のディスクスペースが必要です。
2 リクエストは強制か非強制か、そして強制の場合は強制解放かそうでないかということもあり得ます。 この情報は、pre-receiveフックでは(updateフックでも)利用できません。これは、えーと、つまり、こうです。 いまいち が、これを追加するのは互換性の問題がある。 でも、ほとんど問題なく使えます。 フックは、それが 新規作成 または 既存の参照を削除する なぜなら、もしそうなら、2つのハッシュIDのうちoldかnewのどちらかが、all-zeroの "null hash" (これは予約されています。all-zeroになるハッシュIDは許可されていません) になってしまうからです。
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] git pull」と「git fetch」の違いは何ですか?
-
[解決済み] コミット前に 'git add' を取り消すにはどうすればよいですか?
-
[解決済み] リモートのGitブランチをチェックアウトするには?
-
[解決済み] Git リポジトリを以前のコミットに戻すにはどうすればよいですか?
-
[解決済み] 現在のGit作業ツリーからローカル(未追跡)ファイルを削除する方法
-
[解決済み] Git で、ステージされていない変更を破棄するにはどうしたらいいですか?
-
[解決済み】"git pull" でローカルファイルを強制的に上書きするには?
-
[解決済み】ローカルの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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】git revert <hash> not allowed due to a merge but no -m option was given.
-
[解決済み】マージ後のコミットでGitエラー - fatal: マージ中に部分コミットができない
-
[解決済み】なぜ「git commit」は私の変更を保存しないのですか?
-
git revert + git rebase 一度に複数のコミット_本然233的博客程式员息信网_git revert Multiple
-
[解決済み] git stashを元に戻す
-
[解決済み] 現在の支店にはトラッキング情報がありません
-
[解決済み] git でディレクトリ階層が異なる 2 つのブランチをマージするには?
-
[解決済み] git リモートリポジトリには、ローカルブランチにマージされていないコミットが含まれています。
-
[解決済み] ssh-keygen' は内部コマンドまたは外部コマンドとして認識されません。
-
[解決済み] リモートブランチにプッシュできない、ブランチに解決できない