web-dev-qa-db-ja.com

「git pull Origin mybranch」は、ローカルmybranch NをOriginより先にコミットします。どうして?

私は理解できないgit pullについて奇妙なことを観察しました。

金曜日、私は地元の支部で働きました。 mybranchと呼びましょう。オフィスを出る前に、Origin(私のgithubリポジトリ)にプッシュしました:git Push Origin mybranch

昨日、自宅でラップトップにpulledし、さらにコーディングを行ってから、変更をgithub(Origin)に戻しました。

今、私は仕事を再開し、昨日から私のマシンに変更を加えようとしました(週末には職場のローカルリポジトリに何も変更しませんでした)。

git pull Origin mybranch

これにより、早送りマージが発生しました。これは問題ありません。その後、git statusを実行し、次のように言いました。

# On branch mybranch
# Your branch is ahead of 'Origin/mybranch' by 6 commits.
#
nothing to commit (working directory clean)

え?週末に触れずに、元からプルしただけで6コミット先になりますか?そのため、git diff Origin/mybranchを実行しましたが、差分はちょうどリモートから取得した6つの変更でした。

git fetch Originを実行することでのみこれを「修正」できました。

From [email protected]:me/project
af8be00..88b0738  mybranch -> Origin/mybranch

どうやら、私のローカルリポジトリにはいくつかの参照オブジェクトがありませんでしたが、どうすればそれができますか?つまり、プルは既にフェッチを行っており、そのブランチ以外には何もしていなかったので、git fetch Origingit fetch Origin mybranchは同じ結果になるはずです。

git pull Originではなくgit pull Origin branchnameを常に使用する必要がありますか?

よくわかりません。

91
Matthias

git pullは、明示的にフェッチされたヘッド(または、リモートブランチがマージ用に構成されていない場合)を現在のブランチにマージする前に、適切なパラメーターでgit fetchを呼び出します。

構文:git fetch <repository> <ref>ここで、<ref>はコロンなしのブランチ名であり、指定されたリモートの追跡されたすべてのブランチの標準フェッチを行わず、代わりに単にフェッチする「ワンショット」フェッチです。 FETCH_HEADへの名前付きブランチ。

pdate: 1.8.4以降のGitバージョンの場合、フェッチを要求したrefを追跡するリモート追跡ブランチがある場合、追跡ブランチはfetchによって更新されるようになりました。この変更は、以前の動作が引き起こした混乱を避けるために特に行われました。

git pull <repository> <ref>を実行すると、上記のようにFETCH_HEADが更新され、チェックアウトHEADにマージされますが、リモートリポジトリの標準追跡ブランチは更新されません(Git <1.8。 4)。これは、ローカルブランチがリモートブランチの前にいるように見えることを意味しますが、実際には最新の状態です。

個人的には、git fetchに続いてgit merge <remote>/<branch>を実行します。これは、マージする前に強制更新に関する警告が表示され、マージする内容をプレビューできるためです。git pull aを使用した場合私がやるよりも、ほとんどの場合、パラメーターなしでgit pullbranch.<branch>.remoteに依存して、「正しいことをする」という単純なbranch.<branch>.mergeを実行します。

113
CB Bailey

git remote -v showは、原点になると戻りますか?

Originがgithubをポイントしている場合、ステータスは最新であり、リモートリポジトリより先ではありません。少なくとも、Git1.6.5では、簡単なテストに使用しています。

とにかく、これを避けるために、masterブランチのリモートリポジトリを明示的に定義します。

$ git config branch.master.remote yourGitHubRepo.git

その後、git pull Origin master、その後にgit statusは、クリーンステータスを返します(先行なし)。
なぜ? get fetch Originマスター(git pull Originマスターに含まれる)は、単にFETCH_HEADCharles Bailey彼の答え で説明していますが、alsoも更新しますローカルGitリポジトリ内の「リモートマスターブランチ」。
その場合、ローカルマスターはリモートマスターの「先」にあるようには見えません。


Git1.6.5でこれをテストできます:

最初にワークレポを作成します:

PS D:\git\tests> cd pullahead
PS D:\git\tests\pullahead> git init workrepo
Initialized empty Git repository in D:/git/tests/pullahead/workrepo/.git/
PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo firstContent > afile.txt
PS D:\git\tests\pullahead\workrepo> git add -A 
PS D:\git\tests\pullahead\workrepo> git commit -m "first commit"

ベアリポジトリ(どこからでもプッシュを受信できるリポジトリ)を作成して、GitHubリポジトリをシミュレートします

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone --bare workrepo github

作業中のリポジトリにmodifを追加し、githubリポジトリにプッシュします(リモートとして追加)

PS D:\git\tests\pullahead> cd workrepo
PS D:\git\tests\pullahead\workrepo> echo aModif >> afile.txt
PS D:\git\tests\pullahead\workrepo> git ci -a -m "a modif to send to github"
PS D:\git\tests\pullahead\workrepo> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo> git Push github

GitHubのクローンを作成したホームリポジトリを作成し、そこにいくつかの変更を加えてGitHubにプッシュします。

PS D:\git\tests\pullahead\workrepo> cd ..
PS D:\git\tests\pullahead> git clone github homerepo
PS D:\git\tests\pullahead> cd homerepo
PS D:\git\tests\pullahead\homerepo> type afile.txt
firstContent
aModif

PS D:\git\tests\pullahead\homerepo> echo aHomeModif1  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a first home modif"
PS D:\git\tests\pullahead\homerepo> echo aHomeModif2  >> afile.txt
PS D:\git\tests\pullahead\homerepo> git ci -a -m "a second home modif"
PS D:\git\tests\pullahead\homerepo> git Push github

その後、最初の実験のためにワークレポのクローンを作成します

PS D:\git\tests\pullahead\workrepo4> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo2
Initialized empty Git repository in D:/git/tests/pullahead/workrepo2/.git/
PS D:\git\tests\pullahead> cd workrepo2
PS D:\git\tests\pullahead\workrepo2> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo2> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)

そのレポでは、gitステータスは 'Origin'の前にマスターゲーイングを示しています:

PS D:\git\tests\pullahead\workrepo5> git status
# On branch master
# Your branch is ahead of 'Origin/master' by 2 commits.
#
nothing to commit (working directory clean)

しかし、それはOriginがgithubではないだけです:

PS D:\git\tests\pullahead\workrepo2> git remote -v show
github  d:/git/tests/pullahead/github (fetch)
github  d:/git/tests/pullahead/github (Push)
Origin  D:/git/tests/pullahead/workrepo (fetch)
Origin  D:/git/tests/pullahead/workrepo (Push)

しかし、Originからgithub(またはOriginがまったくなく、リモートの 'github'が定義されている)を持つレポでシーケンスを繰り返すと、ステータスはクリーンです:

PS D:\git\tests\pullahead\workrepo2> cd ..
PS D:\git\tests\pullahead> git clone workrepo workrepo4
PS D:\git\tests\pullahead> cd workrepo4
PS D:\git\tests\pullahead\workrepo4> git remote rm Origin
PS D:\git\tests\pullahead\workrepo4> git remote add github d:/git/tests/pullahead/github
PS D:\git\tests\pullahead\workrepo4> git pull github master
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From d:/git/tests/pullahead/github
 * branch            master     -> FETCH_HEAD
Updating c2763f2..75ad279
Fast forward
 afile.txt |  Bin 46 -> 98 bytes
 1 files changed, 0 insertions(+), 0 deletions(-)
PS D:\git\tests\pullahead\workrepo4> git status
# On branch master
nothing to commit (working directory clean)

Originを指すgithubしかなかった場合、statusはgit1.6.5ではクリーンになります。
以前のgitについては「先」の警告があるかもしれませんが、とにかくgit config branch.master.remote yourGitHubRepo.git明示的に定義されていれば、初期バージョンのGitであっても、それを処理できるはずです。

3
VonC

git remote add NAME URLを使用して、すべてのリモート(元のクローンに付属するOriginを除く)を慎重に追加しますか? git configに追加されたばかりのときにこのバグを見ました。

2
Pat Notz