1. ホーム
  2. ギット

[解決済み】Gitでブランチポイントを見つける?

2022-04-15 02:02:20

質問

私は、master と A のブランチを持つリポジトリを持っており、この 2 つのブランチ間で多くのマージ活動が行われています。master を基にしてブランチ A が作成されたときのコミットをリポジトリで見つけるにはどうしたらよいでしょうか?

私のリポジトリは基本的にこのような感じです。

-- X -- A -- B -- C -- D -- F  (master) 
          \     /   \     /
           \   /     \   /
             G -- H -- I -- J  (branch A)

リビジョンAを探しているのですが、これは何の git merge-base (--all) が見つかります。

どのように解決するのですか?

同じことを探していたら、この質問を見つけました。 ご質問ありがとうございます。

しかし、ここで見る回答は、どうも かなり は、あなたの求める(あるいは私が探していた)答えを与えているようです。 G コミットではなく A コミットします。

そこで、以下のようなツリー(文字が時系列に割り当てられている)を作成し、いろいろとテストしてみました。

A - B - D - F - G   <- "master" branch (at G)
     \   \     /
      C - E --'     <- "topic" branch (still at E)

なぜなら、私は(あなたのグラフではなく、このグラフを参照して)Bを得たが、Aではない(そしてDやEでもない)ことを確認したかったからです。 以下は SHA プレフィックスとコミットメッセージに付けられた文字です (私のレポは以下のサイトからクローンできます) こちら もし、どなたか興味を持たれた方がいらっしゃれば、教えてください。)

G: a9546a2 merge from topic back to master
F: e7c863d commit on master after master was merged to topic
E: 648ca35 merging master onto topic
D: 37ad159 post-branch commit on master
C: 132ee2a first commit on topic branch
B: 6aafd7f second commit on master before branching
A: 4112403 initial commit on master

で、その 目標:Bを見つける . ちょっといじってみて見つけた3つの方法を紹介します。


1. 視覚的に、gitkを使用する。

視覚的にこのようなツリーが見えるはずです(masterから見た場合)。

またはこちら(トピックから見た場合)。

であるコミットを選択しました。 B をグラフにしました。 クリックすると、グラフのすぐ下にあるテキスト入力フィールドに、その完全なSHAが表示されます。


2.視覚的に、ただし端末から。

git log --graph --oneline --all

(編集/余談) --decorate また、ブランチ名やタグなどの表示を追加するのも面白いでしょう。 下の出力には反映されていないので、上のコマンドラインには追加していません)。

を示すもので、(仮に git config --global color.ui auto ):

あるいは、ストレートテキストで。

* a9546a2 トピックからマスタにマージする
|\  
| * 648ca35 マスターをトピックにマージする
| |\  
| | 132ee2a トピックブランチでの最初のコミット
| | e7c863d masterがtopicにマージされた後にmasterにコミットする。
| |/  
|/|   
| 37ad159 マスターブランチ後のコミット
|/  
* 6aafd7f ブランチする前にマスター上で2回目のコミット
* 4112403 マスタへの最初のコミット

どちらの場合でも、6aafd7f のコミットが最低共通点であることがわかります。 B 私のグラフでは A を表示します。


3. シェルマジックで

質問には、上記のようなものが欲しいのか、それとも1つのリビジョンだけを取得し、他は何もしないコマンドが欲しいのかが明記されていませんね。 では、後者を紹介しましょう。

diff -u <(git rev-list --first-parent topic) \
             <(git rev-list --first-parent master) | \
     sed -ne 's/^ //p' | head -1
6aafd7ff98017c816033df18395c5c1e7829960d

また、~/.gitconfig に次のように記述します。 (注意: 末尾のダッシュは重要です。 ブライアン を表示します) :

[alias]
    oldest-ancestor = !zsh -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -

これは、次のような(引用で複雑になっている)コマンドラインで実行できます。

git config --global alias.oldest-ancestor '!zsh -c '\''diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne "s/^ //p" | head -1'\'' -'

zsh は、同じように簡単に bash しかし sh 意志 ない が動作します。 <() の構文はバニラには存在しません。 sh . (このページの別の回答へのコメントで気づかせてくれた@connyさん、改めてありがとうございました!)

注)上記の代替バージョンです。

ありがとうございます ロリ に対して 指摘 同一ブランチを比較する際に上記が破綻する可能性があることを指摘し、sed フォームをミックスから削除し、これを "より安全にする代替 diff フォームを考え出しました(つまり master と master を比較した場合でも結果(つまり最新のコミット)を返します)。

.git-configの行として。

[alias]
    oldest-ancestor = !zsh -c 'diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1' -

シェルから

git config --global alias.oldest-ancestor '!zsh -c '\''diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1'\'' -'

私のテストツリーでは(しばらく利用できなかったのですが、すみません、復活しました)、master と topic の両方で動作するようになりました(それぞれコミット G と B を与えています)。 lioriさん、代替フォームをありがとうございました。


ということで、私(とliori)が思いついたのがこれです。 これは私のために機能しているようです。 また、便利なエイリアスを追加することができます。

git config --global alias.branchdiff '!sh -c "git diff `git oldest-ancestor`.."'
git config --global alias.branchlog '!sh -c "git log `git oldest-ancestor`.."'

ハッピー・ギトギト!