SHA-1ハッシュ値を指定すると、コミットがどのブランチからのものかを見つける方法はありますか?
Ruby Gritを使用してこれを実現する方法を教えてもらえれば、ボーナスポイント。
SHA-1ハッシュ値を指定すると、コミットがどのブランチからのものかを見つける方法はありますか?
Ruby Gritを使用してこれを実現する方法を教えてもらえれば、ボーナスポイント。
回答:
Dav氏は、情報が直接保存されないことは正しいが、それがあなたがそれを見つけることができないということを意味するわけではない。ここでは、いくつかのことができます。
git branch -a --contains <commit>
これにより、履歴に特定のコミットがあるすべてのブランチがわかります。コミットがすでにマージされている場合、明らかにこれはあまり役に立ちません。
コミットが行われたリポジトリで作業している場合は、reflogでそのコミットの行を検索できます。90日以上経過したreflogはgit-gcによって整理されるため、コミットが古すぎると、それを見つけることができません。つまり、これを行うことができます:
git reflog show --all | grep a871742
コミットa871742を検索します。コミットの最初の7桁はabbreviatd 7を使用する必要があることに注意してください。出力は次のようになります。
a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite
コミットがブランチ「完了」で行われたことを示します。デフォルトの出力では、短縮されたコミットハッシュが表示されるため、完全なハッシュを検索しないでください。検索すると、何も見つかりません。
git reflog show
は実際にはのエイリアスにすぎないgit log -g --abbrev-commit --pretty=oneline
ため、出力形式をいじってgrepでさまざまなものを使用できるようにする場合は、それが出発点です。
コミットが行われたリポジトリで作業していない場合、この場合にできる最善の方法は、reflogを調べて、コミットがリポジトリに最初に導入された時期を見つけることです。運が良ければ、コミットされたブランチをフェッチしました。コミットツリーとreflogの両方を同時に歩くことはできないため、これは少し複雑です。reflogの出力を解析し、各ハッシュを調べて、目的のコミットが含まれているかどうかを確認します。
これはワークフローに依存しますが、適切なワークフローでは、開発ブランチでコミットが行われ、マージされます。これは次のようにして行うことができます。
git log --merges <commit>..
指定されたコミットを祖先として持つマージコミットを確認します。(コミットが一度だけマージされた場合、最初のコミットは後のマージである必要があります。それ以外の場合は、いくつかを調べる必要があると思います。)マージコミットメッセージには、マージされたブランチ名が含まれているはずです。
これを当てにできるようにしたい場合は、--no-ff
オプションを使用git merge
して、早送りの場合でもマージコミットの作成を強制することができます。(ただし、あまり熱心になりすぎないでください。乱用すると難読化する可能性があります。)関連する質問に対するVonCの回答は、このトピックについて詳しく説明しています。
git describe
(注釈付き)タグは枝よりも重要とみなすことができるため、十分です。
--no-ff
オプションを使用して常にマージコミットが存在することを確認できるため、マスターに向かってマージされる特定のコミットのパスを常に追跡できます。
-a
、最初のコマンドにフラグを追加してください。git branch -a --contains <commit>
-r
。
merge --no-ff
場合、マージするときにブランチ名を確実に記録するために使用します。しかし、そうでなければ、ブランチ名を一時的な短いラベルとして考え、説明を永続的なものとしてコミットしてください。「開発中に、これはどの略称で呼ばれたのですか?」「このコミットは何をするのか」ほど重要な質問ではありません。
この単純なコマンドは、魅力のように機能します。
git name-rev <SHA>
例(test-branchはブランチ名です):
git name-rev 651ad3a
251ad3a remotes/origin/test-branch
これでも、次のような複雑なシナリオで機能します。
origin/branchA/
/branchB
/commit<SHA1>
/commit<SHA2>
ここでgit name-rev commit<SHA2>
は、branchBを返します。
git name-rev --name-only <SHA>
ブランチ名だけを取得する方が便利であることがわかりました。私の質問...それはどんな状況でも複数のブランチを返すことができますか?
2013年12月の更新:
git-what-branch
(Perlスクリプト、以下を参照)はもう保守されていないようです。git-when-merged
Pythonで書かれた代替手段であり、私にとって非常にうまく機能しています。
これは、「特定のコミットを含むマージコミットの検索」に基づいています。
git when-merged [OPTIONS] COMMIT [BRANCH...]
コミットが1つ以上のブランチにマージされた時期を見つけます。指定されたBRANCHに
もたらさCOMMIT
れたマージコミットを見つけます。具体的に
BRANCH
は、COMMIT
を祖先として含む最初の親の履歴で最も古いコミットを探します。
2010年9月の元の回答:
Sebastien Doucheがひねりました(このSOの回答の16分前):
git-what-branch:コミットがどのブランチにあるか、またはどのようにして名前付きブランチに到達したかを発見します
これは、Perlスクリプトからのセス・ロバートソン非常に興味深いと思われます。
あらすじ
git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...
概要
要求されたコミットが名前付きブランチに到達するためのコミットとマージの最も早い因果パスを(デフォルトで)教えてください。名前付きブランチで直接コミットが行われた場合、それが明らかに最も早いパスです。
最も早い因果パスとは、(
--topo-order
指定されていない限り)コミット時刻までに最も早く名前付きブランチにマージされたパスを意味します。パフォーマンス
多くのブランチ(たとえば、数百)にコミットが含まれている場合、システムはパスを追跡するのに長い時間がかかる可能性があります(Linuxツリーでの特定のコミットの場合、ブランチの探索に8秒かかりましたが、200を超える候補ブランチがありました)。各コミットに。
特定の選択--reference-branch --reference tag
調べる数百倍速くなります(候補ブランチが数百ある場合)。例
# git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May 5 08:59:37 2005)
v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May 3 18:27:24 2005)
v2.6.12-rc3-461-g84e48b6 is on master
v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
[...]
このプログラムは、関心のあるコミットをチェリーピッキングする効果を考慮せず、マージ操作のみを考慮します。
git-what-branch
もうメンテナンスされていないようです。git-when-mergedは、Pythonで書かれた代替手段であり、私にとって非常にうまく機能しています。
たとえば、そのc0118fa
コミットが次のように行われたことを確認するにはredesign_interactions
:
* ccfd449 (HEAD -> develop) Require to return undef if no digits found
* 93dd5ff Merge pull request #4 from KES777/clean_api
|\
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| * a435005 Merge branch 'redesign_interactions' into clean_api
| |\
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event
あなたは実行する必要があります:
git log c0118fa..HEAD --ancestry-path --merges
下にスクロールして、最後のマージコミットを見つけます。それは:
commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date: Sat Oct 1 00:54:18 2016 +0300
Merge branch 'redesign_interactions' into clean_api
更新
または、ただ1つのコマンド:
git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
git merge -m"Any String Here"
、ソースとターゲットのブランチ情報は不明瞭になります。
Merge: f6b70fa d58bdcb
。マージコミットには同じ名前を付けることができます。私には問題はありません
git branch --contains <ref>
これを行う最も明白な「磁器」コマンドです。「配管」コマンドのみで同様のことをしたい場合:
COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
echo $BRANCH
fi
done
(このSO回答からのクロスポスト)
khichar.anilは彼の答えでこれのほとんどをカバーしました。
リビジョン名リストからタグを削除するフラグを追加しています。これは私たちに与えます:
git name-rev --name-only --exclude=tags/* $SHA
貧乏人のオプションが使用することですツールtig
1上にHEAD
、コミットを検索して、視覚的にバックアップマージが見られてコミットするまでコミットそれからラインに従ってください。デフォルトのマージメッセージは、どのブランチがどこにマージされるかを指定する必要があります:)
1 Tigは、Gitのncursesベースのテキストモードインターフェイスです。主にGitリポジトリブラウザーとして機能しますが、チャンクレベルでのコミットの変更のステージングを支援し、さまざまなGitコマンドからの出力のページャーとして機能することもできます。
実験として、現在チェックアウトされているブランチに関する情報をコミットメタデータに格納するポストコミットフックを作成しました。また、gitkを少し変更して、その情報を表示しました。
こちらでチェックできます:https : //github.com/pajp/branch-info-commits
OPが特定のコミットが作成されたときにブランチがたどった履歴を特定しようとしている場合(「SHA-1ハッシュ値を指定すると、コミットがどのブランチからのものであるかを見つける」)、reflogがないと何もありません。どの名前付きブランチがどのコミット履歴にバインドされたかを示すGitオブジェクトデータベースのレコード。
(コメントへの回答として、これを回答として投稿しました。)
うまくいけば、このスクリプトは私の要点を示しています。
rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email e@x.io
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
出力には、「Add f1」を使用したコミットがリモートクローン/ tmp / r2のブランチb1またはb2のどちらから行われたかを知る方法がないことが示されています。
(ここの出力の最後の行)
+ cd /tmp/r1
+ git log --oneline --graph --decorate
* f0c707d (HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|\
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
git log 80c10e5..HEAD --ancestry-path --merges --oneline --color | tail -n 1
とgit log 086c9ce..HEAD --ancestry-path --merges --oneline --color | tail -n 1
コマンドは何ですか?
$ git log HEAD^1..HEAD --ancestry-path --merges --oneline --color | tail -n 1
どの利回り376142d merge branches
と$ git log HEAD^2..HEAD --ancestry-path --merges --oneline --color | tail -n 1
利回り376142d merge branches
-マージ(私が主張したよう)要約を、コミットされショーマージが作成されたときに、おそらく、マージの分岐履歴を難読化、上書きすることができます。
シェルの終了ステータスが気になる場合は、以下を使用してください。
branch-current
-現在のブランチの名前branch-names
-クリーンなブランチ名(1行に1つ)branch-name
-ブランチが1つだけ返されるようにする branch-names
とはどちらも引数としてcommit branch-name
をbranch-names
受け入れ、HEAD
何も指定されていない場合はデフォルトになります 。
branch-current = "symbolic-ref --short HEAD" # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #" # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"
% git branch-name eae13ea
master
% echo $?
0
0
です。% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
1
です。終了ステータスのため、これらは安全に構築できます。たとえば、リモートをフェッチに使用するには:
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
ローカルブランチを見つけるには:
grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'
リモートブランチを見つけるには:
grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'