特定のブランチのみのコミットを取得するためのGitログ


214

特定のブランチの一部であるすべてのコミットをリストしたい。

以下を使用すると、ブランチからのすべてのコミットがリストされますが、親(マスター)からのコミットもリストされます

git log mybranch

私が見つけた他のオプションは、マスターが到達可能なコミットを除外して、私が欲しいものを与えることでしたが、他のブランチ名を知る必要を避けたいです。

git log mybranch --not master

私は使用しようとしましたgit for-each-refが、それはまたmybranchをリストしているので、実際にはすべてを除外しています:

git log mybranch --not $(git for-each-ref --format '^%(refname:short)' refs/heads/)

更新:

私はしばらく前に見つけた新しいオプションをテストしていますが、今までこれが私が探していたものである可能性があるようです:

git log --walk-reflogs mybranch

更新(2013-02-13T15:08):

--walk-reflogsオプションは適切ですが、reflogsの有効期限があることを確認しました(デフォルトは90日、gc.reflogExpire)。

私が探していた答えを見つけたと思います:

git log mybranch --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v "refs/heads/mybranch")

使用可能なブランチのリストから現在のブランチを削除し、そのリストをログから除外しています。この方法では、mybranchによってのみ到達されるコミットのみを取得します



同じ質問はすでに見ましたが、同じではありませんでした
dimirc

2
それでよろしいですか?「アップストリームにないブランチ上のもの」、または「マスターにないブランチ上のもの」というターゲットを念頭に置いた方がよいと思います。さらに、gitはプルーニングが高速ですが、ブランチが多いほど、コストが高くなります。bzrの「missing」コマンドの後に「git missing」と呼ぶスクリプトを使用しています。github.com/jszakmeister/etc/blob/master/git-addons/git-missingで見つけることができます。
John Szakmeister 2013

1
実際にはポスト受信フックにこれが必要なので、「マスター」は常に除外するブランチではありません
dimirc

はい、StarPinkERによって言及された重複は私にとってうまくいきました:git log $(git merge-base HEAD branch).. branch
charo

回答:


165

あなたが使用しているように思われるものからcherry

git cherry -v develop mybranch

これにより、mybranch内に含まれているが、開発中のすべてのコミットが表示されます。最後のオプション(mybranch)を省略すると、代わりに現在のブランチが比較されます。

VonCが指摘したように、常にブランチを別のブランチと比較しているので、ブランチを知ってから、比較するブランチを選択します。


4
これはまさに私が必要とするものですが、これにはより直感的なコマンド(Gitの世界でもそうです)があるはずです。
Seth

12
git cherry -v master現在のブランチとマスターブランチを比較することもできます。
ピティコス2016年

2
git cherryを使用する際の危険性は、ブランチ間でファイルの差分が同一である場合にのみコミットが一致することです。1つのブランチと別のブランチとの間で差分が異なるようなマージが行われた場合、git cherryはそれらを異なるコミットと見なします。
Ben

これだけだfatal: Unknown commit mybranch
Matt Arnold

1
@MattArnoldは、テキスト「develop」と「mybranch」を、リポジトリに存在するブランチに変更する必要があります
Smilie

40

しかし、私は他のブランチ名を知る必要を避けたいと思います。

git diffが十分に表示されない」で説明されているように、Gitのブランチは常に別のブランチまたは少なくとも別のコミットに基づいています

ここに画像の説明を入力してください

正しいコミットを表示するには、ログの参照ポイントが必要です。

GIT-どこから分岐したのですか?」で述べたように:

ブランチは、DAG内の特定のコミットへの単なるポインタです

したがってgit log master..mybranch、1つの回答であっても、にmybranch基づいている場合myotherbranch、それ自体がに基づいている場合は、あまりにも多くのコミットが表示されmasterます。

その参照(ブランチの起点)を見つけるには、次のようにコミットを解析して、コミットがどのブランチにあるかを確認するだけです。


26

ようやくOPが望むことを行う方法を見つけました。それは次のように簡単です:

git log --graph [branchname]

このコマンドは、提供されたブランチから到達可能なすべてのコミットをグラフの形式で表示します。ただし、*コミット行の最初の文字であるコミットグラフを見ると、そのブランチのすべてのコミットを簡単にフィルタリングできます。

たとえば、git log --graph master以下のcakephp GitHubリポジトリの抜粋を見てみましょう:

D:\Web Folder\cakephp>git log --graph master
*   commit 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4
|\  Merge: c3f45e8 0459a35
| | Author: José Lorenzo Rodríguez <lorenzo@users.noreply.github.com>
| | Date:   Tue Aug 30 08:01:59 2016 +0200
| |
| |     Merge pull request #9367 from cakephp/fewer-allocations
| |
| |     Do fewer allocations for simple default values.
| |
| * commit 0459a35689fec80bd8dca41e31d244a126d9e15e
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Mon Aug 29 22:21:16 2016 -0400
| |
| |     The action should only be defaulted when there are no patterns
| |
| |     Only default the action name when there is no default & no pattern
| |     defined.
| |
| * commit 80c123b9dbd1c1b3301ec1270adc6c07824aeb5c
| | Author: Mark Story <mark@mark-story.com>
| | Date:   Sun Aug 28 22:35:20 2016 -0400
| |
| |     Do fewer allocations for simple default values.
| |
| |     Don't allocate arrays when we are only assigning a single array key
| |     value.
| |
* |   commit c3f45e811e4b49fe27624b57c3eb8f4721a4323b
|\ \  Merge: 10e5734 43178fd
| |/  Author: Mark Story <mark@mark-story.com>
|/|   Date:   Mon Aug 29 22:15:30 2016 -0400
| |
| |       Merge pull request #9322 from cakephp/add-email-assertions
| |
| |       Add email assertions trait
| |
| * commit 43178fd55d7ef9a42706279fa275bb783063cf34
| | Author: Jad Bitar <jadbitar@mac.com>
| | Date:   Mon Aug 29 17:43:29 2016 -0400
| |
| |     Fix `@since` in new files docblocks
| |

あなたが見ることができるように、唯一のコミット8314c2ff833280bbc7102cb6d4fcf62240cd3ac4c3f45e811e4b49fe27624b57c3eb8f4721a4323b持って*行をコミットの最初の文字であること。これらのコミットはマスターブランチからのもので、他の4つは他のブランチからのものです。


11

次のシェルコマンドはあなたが望むことをするはずです:

git log --all --not $(git rev-list --no-walk --exclude=refs/heads/mybranch --all)

注意事項

あなたがいる場合はmybranch、チェックアウト、上記のコマンドは動作しません。これは、上のコミットにmybranchもから到達できるHEADため、Gitはコミットをに固有のものとは見なしませんmybranchmybranchがチェックアウトされたときに機能するようにするには、の除外も追加する必要がありますHEAD

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD \
    --all)

しかし、あなたがすべきではない除外しHEADない限り、mybranchそうでない場合は、あなたがに排他的ではありませんコミットを示すリスク、チェックアウトされていますmybranch

同様origin/mybranchに、ローカルmybranchブランチに対応する名前のリモートブランチがある場合は、それを除外する必要があります。

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --all)

また、リモートブランチがリモートリポジトリのデフォルトブランチである場合(通常はにのみ当てはまりますorigin/master)、origin/HEAD同様に除外する必要があります。

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

あなたはブランチをチェックアウトしている、場合およびリモートブランチがあります、およびリモートブランチは、リモートリポジトリのデフォルトです、あなたは多くのことを除いて終了します:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD
    --exclude=refs/remotes/origin/mybranch \
    --exclude=refs/remotes/origin/HEAD \
    --all)

説明

このgit rev-listコマンドは低レベル(配管)コマンドであり、指定されたリビジョンを調べ、検出されたSHA1識別子をダンプします。git logSHA1のみを表示することを除いて、それと同等であると考えてください。ログメッセージ、作成者名、タイムスタンプ、その「派手な」ものはありません。

この--no-walkオプションは、名前が示すようにgit rev-list、祖先チェーンを歩くことを防ぎます。したがって、入力git rev-list --no-walk mybranchすると、SHA1識別子が1つだけ出力されますmybranch。ブランチのチップコミットの識別子です。

--exclude=refs/heads/mybranch --all引数は教えgit rev-listを除く各リファレンスから開始しますrefs/heads/mybranch

したがって、を実行するとgit rev-list --no-walk --exclude=refs/heads/mybranch --all、Gitはを除く各参照のチップコミットのSHA1識別子を出力しrefs/heads/mybranchます。これらのコミットとその祖先は、興味のないコミットです。これらは、表示したくないコミットです。

他のコミットは、あなたが見たいものですので、我々はの出力を収集git rev-list --no-walk --exclude=refs/heads/mybranch --allし、すべてのものが、それらのコミットや先祖を表示するためにGitのを教えてください。

--no-walk引数には、大規模なリポジトリのために必要である(と小さなリポジトリの最適化で):それがなければ、Gitは印刷しなければならない、とシェルは(メモリ内と店舗)を収集しなければならない多くの人が必要以上の識別子をコミットします。大きなリポジトリでは、収集されたコミットの数がシェルのコマンドライン引数の制限を簡単に超える可能性があります。

Gitバグ?

私は以下がうまくいくと期待していました:

git log --all --not --exclude=refs/heads/mybranch --all

しかし、そうではありません。これはGitのバグだと思いますが、おそらく意図的なものです。


いい説明。+1
VonC

5
Mercurialの使い方を知りたくてここに来ましたhg log -b <branch>。gitが非友好的だと言われる理由がわかりません。/ s
weberc2

なぜgit log --all --not --exclude=refs/heads/mybranch --all機能しないのかわかりませんgit log refs/heads/mybranch --not --exclude=refs/heads/mybranch --allが、HEADとoriginを除外する場合と同じ注意事項があります。
ベンC

8

速い答え:

git log $(git merge-base master b2)..HEAD

まあ言ってみれば:

  1. あなたがマスターブランチを持っていること

  2. いくつかのコミットを行う

  3. b2という名前のブランチを作成しました

  4. するgit log -n1; コミットIDは、b2とマスターの間のマージベースです。

  5. b2でいくつかのコミットを行う

  6. git log b2とマスターのログ履歴を表示します

  7. コミット範囲を使用します。コンセプトに慣れていない場合は、ググる、またはオーバーフローをスタックすることをお勧めします。

    あなたの実際のコンテキストでは、たとえば

    git log commitID_FOO..comitID_BAR
    

    「..」は、logコマンドの範囲演算子です。

    つまり、単純な形式で、すべてのログをcommitID_FOOよりも新しいものにしてください...

  8. マージベースのポイント#4を見てください。

    だから:git log COMMITID_mergeBASE..HEAD違いをお見せします

  9. Gitはこのようにマージベースを取得できます

    git merge-base b2 master
    
  10. 最後に、次のことができます。

    git log $(git merge-base master b2)..HEAD
    

4

あなたはこのようなことを試すことができます:

#!/bin/bash

all_but()
{
    target="$(git rev-parse $1)"
    echo "$target --not"
    git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
    while read entry
    do
        eval "$entry"

        test "$ref" != "$target" && echo "$ref"
    done
}

git log $(all_but $1)

または、Gitユーザーマニュアルのレシピから借用します

#!/bin/bash
git log $1 --not $( git show-ref --heads | cut -d' ' -f2 | grep -v "^$1" )

+1。私はあなたのブランチの起源を見つけるためにコミットを解析する必要があると私の回答に書いていました、そしてあなたはまさにそれをしたようです。
VonC 2013

log --walk-reflogsを使用しましたか?私はこのオプションについて読んでいて、今までに必要な結果を提供しています(まだテスト中です)
dimirc

@dimirc Reflogは、すべてが異なる獣です。それは一般的に回復の目的で、時間の経過とともに分岐点を記録します。ポスト受信フックで何をしているのかはわかりませんが、説明すれば、問題に対してより賢明な答えを提供できるでしょう。
John Szakmeister 2013

プッシュですべてのコミットメッセージを解析/チェックする必要があるだけです。私がカバーしたいケースは、誰かがマスターで複数のコミットをプッシュし、複数のコミットで新しいブランチを作成する場合です。post-receiveフックは、マスターとnewbranchなどの両方の参照/ブランチに対して行われた変更を確認する必要があります。マスターからコミットできるため、コミットメッセージが2回解析されないように、新しいブランチの境界を知る必要があります。
dimirc 2013

1
はい。次に、私が概説した上記のアプローチは本当にあなたが望むものだと思います。reflogを使用すると、エントリが一定期間後に落ちるので、頭痛の種になると思います。あなたgit show-ref --tagsも使用を見てみたいかもしれません。
John Szakmeister 2013

4
git rev-list --exclude=master --branches --no-walk

でないすべてのブランチのヒントを一覧表示しますmaster

git rev-list master --not $(git rev-list --exclude=master --branches --no-walk)

master他のブランチの履歴にないの履歴のすべてのコミットをリストします。

シーケンス処理は、コミット選択用のフィルターパイプラインを設定するオプションにとって重要であるため、--branches適用されるはずの除外パターンに従う必要があり、--no-walkコミットrev-listが提供されると想定されていないフィルターを提供するフィルターに従う必要があります。


4

これにより、現在のブランチのコミットが出力されます。引数が渡された場合、ハッシュを出力するだけです。

git_show_all_commits_only_on_this_branch

#!/bin/bash
function show_help()
{
  ME=$(basename $0)
  IT=$(cat <<EOF
  
  usage: $ME {NEWER_BRANCH} {OLDER_BRANCH} {VERBOSE}
  
  Compares 2 different branches, and lists the commits found only 
  in the first branch (newest branch). 

  e.g. 
  
  $ME         -> default. compares current branch to master
  $ME B1      -> compares branch B1 to master
  $ME B1 B2   -> compares branch B1 to B2
  $ME B1 B2 V -> compares branch B1 to B2, and displays commit messages
  
  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi

# Show commit msgs if any arg passed for arg 3
if [ "$3" ]
then
  OPT="-v"
fi

# get branch names
OLDER_BRANCH=${2:-"master"}
if [ -z "$1" ]
then
  NEWER_BRANCH=$(git rev-parse --abbrev-ref HEAD)
else
  NEWER_BRANCH=$1
fi

if [ "$NEWER_BRANCH" == "$OLDER_BRANCH" ]
then
  echo "  Please supply 2 different branches to compare!"
  show_help
fi

OUT=$(\git cherry $OPT $OLDER_BRANCH $NEWER_BRANCH)

if [ -z "$OUT" ]
then
  echo "No differences found. The branches $NEWER_BRANCH and $OLDER_BRANCH are in sync."
  exit;
fi

if [ "$OPT" == "-v" ]
then
  echo "$OUT"
else
  echo "$OUT" | awk '{print $2}'
fi

1
これにより、約100の無関係なログメッセージが生成されました。
アーリースティーブンス2018

@ArlieStephensさん、ちょっと試してみました。上記にヘルプとエラーメッセージを追加しました。それがどうなるか教えてください!
Brad Parks

面白い。今あるコードを見ると、気になるブランチがmasterから派生したものであるとすれば、オリジナルと同じくらい簡単かもしれません。現在のコードでは、親ブランチを明示的に指定できました。(IIRC、私のdevブランチはマスターではなくリリースブランチからのものです。)
Arlie Stephens

@ArlieStephens-ええ、私は機能性を変更したとは思わない...私はもう一度それを更新し、いくつかのローカルテストの後にドキュメントをもう少し正確にしました...そして以前あった「冗長」オプションを追加しましたしかし、私はそれを文書化しませんでした
ブラッドパークス

3

次のコマンドを使用しています。

git shortlog --no-merges --graph --abbrev-commit master..<mybranch>

または

git log --no-merges --graph --oneline --decorate master..<mybranch>

1

このアプローチは比較的簡単だと思いました。

支店へのチェックアウト

  1. 走る

    git rev-list --simplify-by-decoration -2 HEAD
    

これにより、2つのSHAが提供されます。

1)ブランチの最後のコミット[C1]

2)ブランチの最初のコミットに親をコミットします[C2]

  1. 今すぐ実行

    git log --decorate --pretty=oneline --reverse --name-status <C2>..<C1>
    

ここでC1とC2は、最初のコマンドを実行したときに取得される2つの文字列です。2番目のコマンドに<>なしでこれらの値を入力します。

これにより、ブランチ内で変更されたファイルの履歴のリストが表示されます。


質問の最初の3行を読むと、作成者がこの正確なコマンドをリストし、なぜそれが探しているものではないのかを説明していることが
わかります

ああ@black_fm私は答えにいくつかの変更を加えました。あなたが今それが便利だと思うなら、あなたはそれを賛成投票することができます。:)
Mustkeem K 2018

0

私の状況では、Git FlowとGitHubを使用しています。これを行うために必要なのは、GitHubで機能ブランチと開発ブランチを比較することだけです。

機能ブランチに対してのみ行われたコミットが表示されます。

例えば:

https://github.com/your_repo/compare/develop...feature_branch_name


「プルリクエストがどのように見えるかを確認したい」という状況に陥った場合、最善の解決策は無視してgit、代わりにGitHubを使用してプルリクエストを作成するか、ブランチを比較することです。
pkamb
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.