なぜGitは私のマスターブランチが「最新」であるにもかかわらず「最新」であると言うのですか?


118

基本的な問題

プロジェクトのファイルからすべてのコードを削除し、変更をローカルgitにコミットしました(意図的に)。やった

git pull upstream master

アップストリームからフェッチしてマージします(したがって、理論的には、削除されたコードを元に戻す必要があります)。

Gitは、すべてが最新であることを教えてくれます。

すべてが間違いなく最新のものではありません-削除されたコードはすべて削除されます。

その他の関連情報

「マスター」というブランチが1つだけあります。

私は最近、次のように上流を追跡するように「マスター」を設定しました。

アップストリームからリモートブランチマスターを追跡するようにセットアップされたブランチマスター。

コマンドのgit branch -vv結果は次のとおりです。

* master 7cfcb29 [upstream/master: ahead 9] deletion test

なぜなぜこれが起こっているのですか?コードに加えた変更をプロジェクトマネージャーに電子メールで送信する寸前です。

更新

私はそれは明白だと思いましたが、とにかくこれが私の目標です:

私のシステムで最新のコードを入手してください。

ここで私の怒りを許しませんが、そのような単純なタスクがなぜそれほど難しいのですか?


1
ソースを削除する場合は、単純な「プル」でプルしてみてください。ローカルの変更をオーバーライドする必要がないことを確認せずに、gitがローカルの変更(この場合は削除)をオーバーライドしないことは明らかです。最初の答えはあなたがそれについてどうやって取り組むことができるかを正確に説明しているようです。
CashCow 2013年

回答:


208

ここでのあなたの基本的な問題は、あなたがgitが何をするのか、なぜgitがそれをするのかを誤解している、または誤解していることだと思います。

他のリポジトリのクローンを作成すると、gitは「あそこ」にあるもののコピーを作成します。また、「」などの「自分の」ブランチラベルを取得master gitツリーの「フルネーム」が(通常は)であるremotes/origin/master(ただし、この場合はremotes/upstream/master)ラベルのコピーを作成します。ほとんどの場合、そのremotes/部分も省略できるので、元のコピーをとして参照できますupstream/master

ここで、いくつかの変更を行っていくつかのファイルにコミットした場合、その変更を加えたのはあなただけです。その間、他の人は他のクローンを作成し、それらのクローンを変更するために(クローンを作成した元の)リポジトリを使用する場合があります。もちろん、変更されたのは彼らだけです。しかし最終的には、誰かが(「プッシュ」またはパッチなどを介して)元の所有者に送り返す変更を持っている可能性があります。

git pullコマンドは、ほとんどただの省略形ですgit fetchが続きますgit merge。これは、これらの2つの操作が実際に行うことを理解する必要があることを意味するため、重要です。

このgit fetchコマンドは、クローン元(またはフェッチする場所として設定されている場所)に戻り、「他の誰かが追加、変更、または削除した新しいもの」を見つけるように指示しています。これらの変更はコピーされ、以前にそれらから取得したもののコピーに適用されます。それらはあなた自身の仕事に適用されず、彼らの仕事にのみ適用されます。

git mergeコマンドは、より複雑であり、あなたがゆがんで行っているところです。少し単純化しすぎますが、「コピーで変更したもの」を「誰か他の人からフェッチして、自分のコピーに追加した変更」と比較します。変更とそれらの変更が競合していないように見える場合は、merge操作によってそれらがまとめられ、開発とそれらの開発を結び付ける「マージコミット」が提供されます(非常に一般的な「簡単な」ケースでは、変更すると、「早送り」されます)。

現在発生している状況は、変更を加えてコミットした状況であり、実際には9回、したがって「9つ前」ですが変更はありません。したがって、fetch忠実に何もフェッチせず、merge変更の欠如を取り、何もしません。

あなたが望むのは、コードの「彼らの」バージョンを見ること、あるいは多分「リセット」することです。

見たいだけの場合は、そのバージョンを確認するだけです。

git checkout upstream/master

これは、現在のディレクトリを、フルネームが実際にあるブランチに移動することをgitに伝えますremotes/upstream/master。最後に実行しgit fetchて最新のコードを取得した時点でのコードが表示されます。

自分の変更すべて破棄したい場合は、ラベルのmaster名前を変更するというgitの考えを変更する必要があります。現在、最新のコミットを示しています。そのブランチに戻った場合:

git checkout master

次に、このgit resetコマンドを使用すると、「ラベルを移動」することができます。残っている唯一の問題(あなたが本当にしたことをすべて放棄する準備ができていると仮定した場合)は、ラベルが指すべき場所を見つけることです。

git log数値の名前を見つけることができます—これら7cfcb29は永続的な(決して変更されない)名前であり、名前を付ける他の方法はとんでもない数がありますが、この場合は名前だけが必要ですupstream/master

独自の変更を一掃、ラベルを移動するには(あなたが犯したすべてのことを非常にしばらくの間、実際に回復可能ですが、それはそうでは多くの困難、この後だ非常に確認してください):

git reset --hard upstream/master

--hard、あなたがやっているものを一掃し、現在のブランチラベルを移動し、コミット与えをチェックアウトするのgitに指示します。

本当にgit reset --hardたくさんの仕事をしたい、一掃したいというのは、あまり一般的ではありません。より安全な方法(結局のところ、その作業の一部に価値があると判断した場合、その作業を簡単に回復できるようにする)は、既存のブランチの名前を変更することです。

git branch -m master bunchofhacks

そして、master「tracks」という名前の新しいローカルブランチを作成します(この用語は人を混乱させると思うので、私はあまり好きではありませんが、それはgit用語です:-))オリジン(またはアップストリーム)マスター:

git branch -t master upstream/master

これで、次のことを実行できます。

git checkout master

最後の3つのコマンドが行うこと(2つのコマンドにするためのショートカットがあります)は、既存のラベルに貼り付けられた名前を変更してから、新しいラベルを作成して、それに切り替えることです。

何かをする前に:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "master"

git branch -m

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

git branch -t master upstream/master

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

以下C0は、最初にを実行したときに取得した最新のコミット(完全なソースツリー)ですgit clone。C1からC9までがコミットです。

次のようにするgit checkout bunchofhacksgit reset --hard HEAD^^、最後の画像が次のように変わることに注意してください。

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 -    "bunchofhacks"
                                                      \
                                                       \- C8 --- C9

その理由はHEAD^^、現在のブランチの先頭から2つ上のリビジョンに名前を付け(リセットの直前はbunchofhacks)してからreset --hard、ラベルを移動するためです。コミットC8とC9はほとんど見えなくなりました(reflogのようなものを使用git fsckしてそれらを見つけることができますが、それほど簡単ではありません)。ラベルは好きなように移動できます。fetchコマンドで始まるものの世話をしますremotes/。「yours」と「theirs」を一致させるのが一般的ですが、「yours」とremotes/origin/mauve名前を付けたいmauve場合はいつでも「theirs」と入力して「コミット」を表示できます。(「1つのコミット」はソースツリー全体であることを思い出してください。git showたとえば、次のようにして、1つのコミットから1つの特定のファイルを選択できます。


12
私はあなたの優れた答えから多くを学びました。しかし、私がgitステータスメッセージを取得する理由についてはまだ混乱しています。アップストリームリポが現在のリポよりもいくつかコミットされていると、「ブランチは 'origin / master'で最新です」と表示されます。git pullで最新の状態にすることができますが、メッセージに「最新の状態です」と表示されている場合、プルする必要があることをどのようにして知ることができますか?
Christopher Werby

@ChristopherWerby:git mergeコマンドラインコマンドとして実行しているように聞こえます(これは私自身が行っていることであり、合理的な方法です)。ただし、git pull最初にを実行しgit fetch次にを実行することで開始することに注意してくださいgit merge(またはgit rebase、代わりに実行するように指示した場合)。マージされる新しいコミット(またはリベースのみ)を実際に引き継ぐのはフェッチステップです。
torek

@torek以外git statusに、アップストリームのリポジトリが現在のリポジトリよりも進んでいるかどうかを確認するために使用できるコマンドはありますか?git status「ブランチは 'origin / master'で最新です」というメッセージが表示され、最新の変更がないと思い込んでしまいます。時々、「origin / masterはあなたのブランチより5コミット先です」(言い換え)のようなメッセージを受け取ります。しかし、それは一貫していません。
Christopher Werby 2015

1
git statusイミディエイトgit fetchが100を超えるオブジェクトをプルダウンし、ほぼ100のデルタを解決するとき、これはまだ「実際にブランチが最新である」と答えず、いくつかの新しいブランチといくつかの新しいタグに言及し、メイン(リモート追跡)ブランチヘッドコミット-そして、別のgitステータスが陽気にそして不誠実に、まだ「ブランチは最新です」と言っています。明らかに、元から多くのものが降りてきましたが、ブランチは前後とも「元で最新」でしたか?
NeilG

1
git pullgit fetch最初に実行し、次にgit merge(または選択した他の2番目のコマンド)。git fetchステップは、更新あなたのGitリポジトリのメモリ自分呼び出してGitリポジトリの状態を、自分のGitをし、そこから新しい何かを取得します。あなたのgit statusGitのあなたのGitのメモリをチェックするだけです。
トレック

18

私はあなたと同じ問題を抱えていました。

私はそうしましたgit status git fetch git pull、しかし私の枝はまだ起源に遅れていました。フォルダーとファイルをリモートにプッシュし、Webでファイルを確認しましたが、ローカルでは見つかりませんでした。

最後に、これらのコマンドは私のローカル上のすべてのファイルとフォルダーを更新しました:

git fetch --all
git reset --hard origin/master 

またはブランチが必要な場合

git checkout your_branch_name_here
git reset --hard origin/your_branch_name_here

1
ありがとう!これは実際に機能しました。ブランチ名は大文字と小文字が区別されることに注意してください!
アンドレ・ラモン

4

プロジェクトファイルをすべて削除するなど、コミットした変更はプル後も引き続き有効です。プルするのは、どこかからの最新の変更を独自のブランチにマージすることだけです。ブランチがすべてを削除した場合、アップストリームの変更が削除したファイルに影響を与えると、せいぜいマージの競合が発生します。つまり、要するに、すべてが最新の状態です。

「すべてのファイルが削除された」のではなく、どのような結果を得たいかを説明した場合、おそらく誰かが適切な行動方針を提案できます。

更新:

私のシステムで最新のコードを入手する

あなたが理解していないように見えるのは、あなたがあなたの最新のコードをすでに持っているということです。masterブランチにある他の誰かの最新仕事を見たい場合は、次のようにします。

git fetch upstream
git checkout upstream/master

これにより、すぐに(再)自分の作業を開始できるようになるわけではありません。自分が行った操作を元に戻す方法や、自分や他の誰かが行った変更を元に戻す方法を知る必要がある場合は、詳細をお知らせください。また、その基本的な目的を誤解しているように見えるので、バージョン管理の目的についても検討してください。


私は実際、私のシステムに他の誰かのコードの最新バージョンが欲しいです。ただし、これら2つのコマンドはそれを行いませんでした。私が得るすべては「ブランチマスターにすでに」です。私のファイルのコードは、他の人のコードを反映していません。
user1971506 2013年

すみません、あったはずupstream/masterです。私の答えを更新しました。
Ryan Stewart

3

他のポスターが言うように、プルは変更を上流からリポジトリにマージします。リポジトリにあるものをアップストリームにあるもので置き換えたい場合、いくつかのオプションがあります。袖口を外して、私は一緒に行きます

git checkout HEAD^1  # Get off your repo's master.. doesn't matter where you go, so just go back one commit
git branch -d master  # Delete your repo's master branch
git checkout -t upstream/master  # Check out upstream's master into a local tracking branch of the same name

1

与えられた情報の幅と深さの点で一番上の答えははるかに優れていますが、問題をほぼ即座に修正して、バージョン管理の基本原則のいくつかを踏み込んで気にしない場合は、...

  1. マスターに切り替え

    $ git checkout upstream master
    
  2. 不要なブランチを削除します。(注:通常の-dフラグの代わりに-Dを指定する必要があります。ブランチがマスターよりも多くのコミットに先行しているためです。)

    $ git branch -d <branch_name>
    
  3. 新しいブランチを作成する

    $ git checkout -b <new_branch_name>
    

1

これらの答えはどれもうまくいきませんでしたが、次のコマンドを使用して問題を修正することができました。

git fetch origin

これは私にとってトリックでした。


0

ローカルにgithubにないファイルがあり、それでもあなたがgit status言うなら、ちょうどフレンドリーなリマインダー

あなたのブランチは 'origin / master'で最新です。コミットするものは何もない、作業ツリーはクリーン

ファイルがある場合に発生する可能性があります .gitignore

実行してみてください

cat .gitignore 

これらのファイルがそこに表示されるかどうかを確認します。それは、gitがそれらをリモートに移動したくない理由を説明します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.