1. ホーム
  2. git

[解決済み] master ブランチは最新ではないのに、Git が "already up to date" と表示するのはなぜですか?

2022-05-12 14:49:04

質問

基本的な問題

プロジェクトのあるファイルからすべてのコードを削除し、その変更をローカルの git に (わざと) コミットしたところです。私が行ったのは

git pull upstream master

を使用して上流から取得し、マージします (したがって、理論的には削除されたコードは戻ってくるはずです)。

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

削除されたコードはすべて削除されたままです。

その他の関連情報

私は "master" という名前のブランチを1つだけ持っています。

最近、上流を追跡するために "master" をこのように設定しました。

<ブロッククオート

ブランチマスターは、上流からのリモートブランチマスターを追跡するように設定されています。

コマンドは git branch -vv が得られます。

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

なぜ、なぜ、なぜ、こんなことになるのでしょうか? 私たちのコードに変更を加えた場合、プロジェクト・マネジャーに電子メールを送るだけでいいという状態になりかけています。

更新情報

当たり前といえば当たり前なんですが、とにかくこれが私の目標です。

私のシステムでコードの最新版を取得する。

しかし、このような単純な作業がなぜこんなに難しいのでしょうか?

解決方法は?

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

他のリポジトリをクローンすると、git はそこにあるすべてのもののコピーを作成します。 また、次のようなブランチラベルも取得します。 master のラベルのコピーを作成し、そのラベルの "フルネーム" を あなたの git ツリーは(通常) remotes/origin/master (ただし、あなたの場合は remotes/upstream/master ). たいていの場合は remotes/ の部分でも、そのオリジナルのコピーを参照することができます。 upstream/master .

もしあなたが今、あるファイルに何らかの変更を加えてコミットすると、その変更を持つのはあなただけです。 一方、他の人は(あなたがクローンを作った)元のリポジトリを使って他のクローンを作り、そのクローンを変更することができます。 もちろん、彼らが変更したのは彼らだけです。 しかし最終的には、誰かが元の所有者に("push"やパッチなどを通じて)変更を送り返すかもしれません。

git pull コマンドは、ほとんどの場合、単に git fetch に続いて git merge . これは、この2つの操作が実際に何を行っているかを理解する必要があることを意味し、重要なことです。

git fetch コマンドは、クローンした場所(あるいは取得する場所として設定した場所)に戻り、誰かが追加したり変更したり削除したりした新しいものを見つけるように言います。 これらの変更はコピーされ、適用されます。 をコピーすることができます。 . それらは ではない 自分の作品に適用され、相手の作品にのみ適用されます。

その git merge コマンドはもっと複雑で、あなたが間違っているところです。 このコマンドが行うことは、少し単純化しすぎですが、「あなたのコピーで変更したこと」と「他の誰かから取得した変更で、あなたのコピーに追加されたその誰かの作業」とを比較することです。 あなたの変更と相手の変更が衝突していないように見える場合は merge を実行すると、それらをまとめて "merge commit" とし、自分の開発と相手の開発を結びつけることができます (ただし、非常によくある "easy" の場合、変更がないので "fast forward" を取得することになります)。

今あなたが遭遇している状況は、あなたが変更を加えてコミットした回数が9回で、それゆえ「先の9回」という表現になっているのです。 いいえ を変更します。 だから fetch はひたすら何も取得せず、次に merge は、その変化のなさを受け止め、また何もしない。

あなたが欲しいのは、彼らのバージョンのコードを見ること、あるいは、おそらくは、彼らのバージョンにリセットすることなのです。

単に見るだけなら、そのバージョンをチェックアウトすればいいだけです。

git checkout upstream/master

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

もし、あなたが 放棄 を変更した場合、どのリビジョンにラベルを付けるかについての git の考え方を変更する必要があります。 master という名前を付ける必要があります。 現在のところ、最新のコミットを指定しています。 もし、そのブランチに戻ったら

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 を追跡します (この用語は人を混乱させると思うのであまり好きではありませんが、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 bunchofhacks で、次に git 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/ . 自分のものと相手のものを一致させるのが一般的です(つまり、相手のものが remotes/origin/mauve 自分の名前を mauve しかし、あなたが彼らから得たコミットに名前を付けたい、あるいは見たいときにはいつでも "彼らのもの、と入力することができます(1つのコミットがソースツリー全体であることを忘れないでください)。 一つのコミットから特定のファイルを選ぶには、次のようにします。 git show 例えば、必要な時に必要な分だけ)