web-dev-qa-db-ja.com

git:ブランチがリモートブランチの前後にどれだけあるかをプログラムで知る

git statusの後に出力される情報を抽出したいと思います。次のようになります。

# On branch master
# Your branch is ahead of 'Origin/master' by 2 commits.

もちろん、git statusの出力を解析することはできますが、この人間が読める形式の出力は変更される可能性があるため、これはお勧めしません。

2つの問題があります:

  1. リモート追跡ブランチを知る方法は?多くの場合Origin/branchですが、そうである必要はありません。
  2. 数字を取得する方法は?それが進んでいるか遅れているかを知る方法は?コミット数は?そして、分岐したブランチケースはどうですか?
45
Olivier Verdier

更新

Amalloyが指摘しているように、最近のバージョンのgitは、追跡ブランチに「branchname @ {upstream}」(または「branchname @ {u}」、または「@ {u}」を指定することで、特定のブランチに一致する追跡ブランチを見つけることをサポートしています。 HEADの)。これは、以下のスクリプトに実質的に取って代わります。できるよ:

git rev-list @{u}..
git rev-list --left-right --boundary @{u}...
gitk @{u}...

たとえば、git qgit log --pretty='...' @{u}..にエイリアスして、プッシュの準備ができている「キューに入れられた」コミットを表示します。

元の回答

いくつかのシェルコマンドで実際的であるよりも多くのgitconfigを解析せずに、一般に追跡ブランチを見つける簡単な方法はないようです。しかし、多くの場合、これは大いに役立ちます。

# work out the current branch name
currentbranch=$(expr $(git symbolic-ref HEAD) : 'refs/heads/\(.*\)')
[ -n "$currentbranch" ] || die "You don't seem to be on a branch"
# look up this branch in the configuration
remote=$(git config branch.$currentbranch.remote)
remote_ref=$(git config branch.$currentbranch.merge)
# convert the remote ref into the tracking ref... this is a hack
remote_branch=$(expr $remote_ref : 'refs/heads/\(.*\)')
tracking_branch=refs/remotes/$remote/$remote_branch
# now $tracking_branch should be the local ref tracking HEAD
git rev-list $tracking_branch..HEAD

別の、より強引なアプローチ:

git rev-list HEAD --not --remotes

jamessanの回答は、$ tracking_branchとHEAD git rev-listを使用)の相対的な違いを見つける方法を説明しています。1つの楽しいことができます。

git rev-list --left-right $tracking_branch...HEAD

($ tracking_branchとHEADの間に3つのドットがあることに注意してください)。これにより、両方の「アーム」でコミットが表示され、前面に識別マークが表示されます。$ tracking_branchでのコミットの場合は「<」、HEADでのコミットの場合は「>」です。

18
araqnid

git rev-list Origin..HEADは、現在のブランチにあるがOriginにはないコミットを表示します。つまり、Originより進んでいるかどうか、どのコミットによって実行されているかを示します。

git rev-list HEAD..Originは反対を表示します。

両方のコマンドがコミットを示している場合は、分岐が分岐しています。

22
jamessan

git branch -v -vを試すことができます。 -vフラグを2回指定すると、アップストリームブランチの名前が出力されます。サンプル出力:

* devel  7a5ff2c [Origin/devel: ahead 1] smaller file status overlay icons
  master 37ca389 [Origin/master] initial project check-in.

このフォーマットはgit status出力よりも安定していると思います。

11
max

編集:私の元の答えは、「Origin」と呼ばれるリモコンをユーザーが持っていることに依存していたため、実際にはあまり良くありませんでした。また、現在のブランチにOrigin-head以外にトラッキングブランチがある場合も失敗しました。これらの欠陥は本質的にそれを役に立たなくしました。ただし、@ araqnidによる回答は最も効率的な方法ではなく、彼が$tracking_branchに到達する方法はまっすぐ進むよりも少ないです。同じ機能を取得するために私が見つけた最も効率的な(最速の)方法は次のとおりです。

# get the tracking-branch name
tracking_branch=$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))
# creates global variables $1 and $2 based on left vs. right tracking
# inspired by @adam_spiers
set -- $(git rev-list --left-right --count $tracking_branch...HEAD)
behind=$1
ahead=$2

元の回答:(劣っていますが、明確にするために与えられています)

おそらく私が見つけることができる最も簡単な方法(@insidepowerに触発された)

# count the number of logs
behind=$(git log --oneline HEAD..Origin | wc -l)
ahead=$( git log --oneline Origin..HEAD | wc -l)

以前は@araqnidのメソッドを使用していましたが、はるかに簡単なので、スクリプトの一部をこのメソッドに移動すると思います。これは、どのUNIXシステムでも機能するはずです。

7
scicalculator

git statusには、スクリプトによる解析を目的とした--porcelainオプションがあります。これは--short出力に基づいています-これらは執筆時点ではほとんど同じです(詳細については、 git status man page の「PorcelainFormat」セクションを参照してください)。主な違いは、--shortにカラー出力があることです。

デフォルトではブランチ情報は表示されませんが、--branchオプションを追加すると、次のような出力が得られます。

git status --short --branch
## master...Origin/master [ahead 1]
?? untrackedfile.txt
...

(フェッチ後)最新の場合、分岐行は次のようになります。

## master

あなたが先にいる場合:

## master...Origin/master [ahead 1]

遅れている場合:

## master...Origin/master [behind 58]

そして両方のために:

## master...Origin/master [ahead 1, behind 58]

git status --porcelain --branch1.7.10. 以降でのみ使用可能であることに注意してください(ただし、git status --short --branch1.7.2 以降使用可能です)。

5
Hamish Downer

最新バージョンのgitでは、@{u}は、現在のブランチが設定されている場合、そのアップストリームを指します。

したがって、リモート追跡ブランチの背後にあるコミットの数を数えるには、次のようにします。

git rev-list HEAD..@{u} | wc -l

リモコンよりどれだけ進んでいるかを確認するには、順序を切り替えるだけです。

git rev-list @{u}..HEAD | wc -l

より人間が読める形式の要約については、代わりにログを要求できます。

git log --pretty=oneline @{u}..HEAD

私自身の目的のために、アップストリームがまだ設定されていない場合に、@{u}を適切な推測に置き換えるスクリプトに取り組んでいます。残念ながら、現時点では、ダウンストリーム(プッシュ先)を表す@{d}はありません。

5
joeytwiddle

なぜこれが機能しないのですか?

#!/bin/sh
git diff Origin/master..HEAD --quiet --exit-code
RETVAL=$?
if [ $RETVAL -gt 0 ]; then
    echo "You need to git Push!"
else
    echo "No git Push necessary!"
fi 
2
Till

リモート追跡ブランチを知る方法は?それはしばしばある Origin/branchしかし、そうである必要はありません。

Git 2.5+では、プッシュ先のブランチを参照する新しいショートカットが導入されています。 @{Push}:ここで関心のあるリモート追跡ブランチになります。

つまり、ブランチにプッシュするように構成されているすべてのブランチの前後を確認する別のオプションがあります。

git for-each-ref --format="%(Push:track)" refs/heads

詳細については、「 プッシュされていないGitコミットの表示 "」を参照してください。

1
VonC

Araqnidの回答のコードの一番上のチャンクは私には機能しないので、おそらくgitの何かが18か月前に書かれてから変更されています。変更すると機能します:

tracking_branch=refs/remotes/$remote/$remote_branch

tracking_branch=$remote/$remote_branch

ただし、ローカルブランチを追跡する場合はまだ問題があります。その場合、リモートパーツ(「。」になります)をトリミングする必要があります。

tracking_branch=${tracking_branch#./}

次に、次のように、プログラムで前後のリビジョン数を取得できます。

set -- `git rev-list --left-right --count $tracking_branch...HEAD`
behind="$1"
ahead="$2"

私はそれをすべて行うためのスクリプトを作成し(さらに-たとえば、git-svnブリッジの反対側にあるリモートを見つけようとすることもできます)、それらを githubの私のgit-configリポジトリ に公開しました。 =。たとえば、これが私の git-compare-upstream です。インストール手順およびその他の便利な関連スクリプトについては、 README を参照してください。

1
Adam Spiers