web-dev-qa-db-ja.com

「git pull」はどのように私の宿題を食べましたか?

私は校長室の子供が、犬が期限が切れる前の夜に宿題を食べたと説明しているように感じますが、私はいくつかのクレイジーなデータ損失のバグを顔で見ていて、どうしてそれが起こったのか理解できません。 gitがリポジトリ全体をどのように使用できるか知りたいのですが!私は何度もgitを絞り込みましたが、点滅することはありません。私は20 Gig Subversionリポジトリを27 gitリポジトリに分割するために使用し、fooをフィルター分岐して混乱を解消しました。これにより、バイトが失われることはありません。 reflogは常にフォールバックして存在します。今回はカーペットがなくなりました!

私の観点からは、実行したのはgit pullそしてそれは私のローカルリポジトリ全体を焼き払った。 「チェックアウトしたバージョンを台無しにした」、「私がいたブランチ」、またはそのようなものだという意味ではありません。つまりすべてがなくなった

これは事件の私の端末のスクリーンショットです:

incident screen shot

それについてご説明します。私のコマンドプロンプトには、現在のgitリポジトリ(preztoのvcs_info実装を使用)に関するデータが含まれているため、gitリポジトリがいつなくなったかを確認できます。最初のコマンドは十分に正常です:

  » caleb » jaguar » ~/p/w/incil.info » ◼  zend ★ »
❯❯❯ git co master
Switched to branch 'master'
Your branch is up-to-date with 'Origin/master'.

そこで、「zend」ブランチにいて、マスターをチェックアウトしました。ここまでは順調ですね。次のコマンドの前のプロンプトで、ブランチが正常に切り替えられたことがわかります。

  » caleb » jaguar » ~/p/w/incil.info » ◼  master ★ »
❯❯❯ git pull
remote: Counting objects: 37, done.
remote: Compressing objects: 100% (37/37), done.
remote: Total 37 (delta 25), reused 0 (delta 0)
Unpacking objects: 100% (37/37), done.
From gitlab.alerque.com:ipk/incil.info
 + 7412a21...eca4d26 master     -> Origin/master  (forced update)
   f03fa5d..c8ea00b  devel      -> Origin/devel
 + 2af282c...009b8ec verse-spinner -> Origin/verse-spinner  (forced update)
First, rewinding head to replay your work on top of it...
>>> elapsed time 11s

そしてちょうどそのようにそれはなくなった。経過時間マーカーは、10秒以上経過した場合、次のプロンプトの前に出力されます。 Gitは、巻き戻しして再生したという通知を超えて、出力を提供しませんでした。終了したことを示すものはありません。

次のプロンプトには、現在のブランチやgitの状態に関するデータは含まれていません。

失敗したことに気付かなかったので、私は知らないうちに別のgitコマンドを実行して、gitリポジトリにいないことを知らされました。 PWDは変更されていません。

  » caleb » jaguar » ~/p/w/incil.info »
❯❯❯ git fetch --all
fatal: Not a git repository (or any parent up to mount point /home)
Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).

この後、見回すと、完全に空のディレクトリにいることがわかりました。何もない。 「.git」ディレクトリはありません。空の。

私のローカルgitはバージョン2.0.2です。ここに何が起こったかを理解するために関連するかもしれない私のgit設定からのいくつかのヒントがあります:

[branch]
        autosetuprebase = always
        rebase = preserve
[pull]
        rebase = true
[rebase]
        autosquash = true
        autostash = true
[alias]
        co = checkout

たとえば、私はgit pull上記の出力の一部が正常であるように、マージではなく常にリベースを行うように設定します。

データを復元できます。他のリポジトリにプッシュされなかった重要ではないスタッシュ以外のgitオブジェクトはなかったと思いますが、何が起こったのか知りたいです

私はチェックしました:

  • Dmesgまたはsystemdジャーナルのメッセージ。遠隔的に関連することすらありません。
  • ドライブまたはファイルシステムの障害を示すものはありません(LVM + LUKS + EXT4はすべて正常に見えます)。 lost + foundには何もありません。
  • 他には何もしませんでした。私が上に表示していない履歴には何もありません。この間、他の端末は使用されていません。間違ったCWDなどで実行された可能性のあるrmコマンドはありません。
  • 別のディレクトリの別のgit repoを突くと、実行中に明らかな異常が表示されませんgit pulls。

ここで他に何を探すべきですか?

53
Caleb

はい、git宿題を食べました。それのすべて。

私は事件後にこのディスクのddイメージを作成し、後でそれをいじりました。システムログから一連のイベントを再構築して、何が起こったかを次のように推測します。

  1. このインシデントの数日前に、システム更新コマンド(pacman -Syu)が発行されていました。
  2. ネットワークの停止が長引いたため、パッケージのダウンロードを再試行する必要がありました。インターネットの欠如に不満を感じていたので、私はシステムをスリープ状態にしてベッドに入れました。
  3. 数日後、システムが起動し、パッケージの検索とダウンロードが再開されました。
  4. たまたまこのリポジトリをいじり回す直前にパッケージのダウンロードが終了しました。
  5. システムglibcインストールは、git checkoutの後、git pullの前に更新されました。
  6. gitバイナリは、git pullの開始後、終了する前に置き換えられました。
  7. そして7日目に、gitはすべての労働から休みました。そして世界を削除したので、他の皆も休まなければなりませんでした。

私は知りません正確にこれを引き起こした競合状態が発生しましたが、操作の途中でバイナリをスワップアウトすることは、確かにナイスでもテスト可能な/繰り返し可能な状態でもありません。通常、実行中のバイナリのコピーはメモリに保存されますが、gitは奇妙であり、バージョン自体を再生成する方法については、この混乱を引き起こしたと確信しています。明らかに、すべてを破壊するのではなく、それは死んだはずですが、それが起こったのです。

6
Caleb

削除するファイルパスの定義に失敗した可能性があります。

あなたのケースは私に手作りのremove(path)メソッドがルートフォルダーを削除しようとしたとき、与えられたパラメーターがOSがルートフォルダーとして修正した空の文字列だったので美しい日を思い出させました。

これは同様のgitバグの可能性があります。そのような:

  1. Rebaseコマンドはremove(project_folder + file_path)(疑似コード)のようなファイルを削除したかった
  2. なんとかして_file_path_は当時は空でした。
  3. コマンドはremove(project_folder)のようなものとして評価されました
2
maliayas

運が良ければ、次のコマンドでこれを修正できます。

git reset --hard ORIG_HEAD  

潜在的な危険な変更が始まると、gitは現在の状態をORIG_HEADに隠します。これを使用すると、マージまたはリベースを元に戻すことができます。

Gitマニュアル:マージの取り消し

1
Routhinator