Git:削除された(リモート)ブランチを復元する


94

プッシュ中に何らかの方法で削除した2つのGitブランチを復元する必要があります。

これらの2つのブランチは別のシステムで作成され、私の「共有」(github)リポジトリにプッシュされました。

私のシステムでは、フェッチ中に(どうやら)ブランチを取得しました。

~/myfolder> git fetch
remote: Counting objects: 105, done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 62 (delta 29), reused 0 (delta 0)
Unpacking objects: 100% (62/62), done.
From github.com:mygiturl
 * [new branch]      contact_page -> origin/contact_page
   731d1bb..e8b68cc  homepage   -> origin/homepage
 * [new branch]      new_pictures -> origin/new_pictures

その後すぐに、ローカルの変更を中央レポに送信するようにプッシュしました。何らかの理由で、これらのブランチはローカルシステムと中央リポジトリの両方から削除されました。

~/myfolder> git push
Counting objects: 71, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (43/43), done.
Writing objects: 100% (49/49), 4.99 KiB, done.
Total 49 (delta 33), reused 0 (delta 0)
To git@github.com:mygiturl.git
 - [deleted]         contact_page
 + e8b68cc...731d1bb homepage -> homepage (forced update)
   bb7e9f2..e0d061c  master -> master
 - [deleted]         new_pictures
   e38ac2e..bb7e9f2  origin/HEAD -> origin/HEAD
   731d1bb..e8b68cc  origin/homepage -> origin/homepage
   e38ac2e..bb7e9f2  origin/master -> origin/master
 * [new branch]      origin/contact_page -> origin/contact_page
 * [new branch]      origin/new_pictures -> origin/new_pictures

自分の出身地の機械から枝を取り除くのはそれほど簡単ではないので、できれば地元の人から枝を取り戻したいと思います。

失ったコミットを回復するためにグーグルで検索したすべてのgit "undo"情報。これらのブランチにはコミットUIDがないため、ここでは当てはまりません。

これらを元に戻す方法を教えてください。また、そもそもそれらがどのように削除されたのか、そして今後どうすればこれを回避できるのかについても知りたいです。

編集:要求に応じて、これが私のリポジトリ設定です

user.name=Craig Walker
user.email=github@softcraft.ca
alias.unadd=reset HEAD
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
remote.origin.url=git@github.com:MyGitURL.git
remote.origin.mirror=true
branch.master.remote=origin
branch.master.merge=refs/heads/master
alias.undo=reset --hard
alias.test=push -f ci HEAD:master
alias.st=status
alias.ci=commit
alias.br=branch
alias.co=checkout
alias.ch=checkout
alias.df=diff
alias.lg=log -p
alias.who=shortlog -s --
remote.ci.url=ContinuousIntegrationGitURL
remote.ci.fetch=+refs/heads/*:refs/remotes/ci/*
branch.photo.remote=origin
branch.photo.merge=refs/heads/photos
remote.foo.url=FooGitURL
remote.foo.fetch=+refs/heads/*:refs/remotes/cynthia/*
branch.homepage.remote=origin
branch.homepage.merge=refs/heads/homepage

フェッチとプッシュの構成が「異常」または一致していないようです。git config -lローカルリポジトリには何が表示されますか?
CBベイリー

かなり可能性があります。投稿しました。
Craig Walker

2
あなたのremote.origin.fetchrefspecはでの使用に適していませんremote.origin.mirror = true。ミラーリングしますか、それともGitHubリポジトリを通常のリモートとして使用しますか?私の答えには、どちらの方法でも必要なコマンドが含まれているはずです。
Chris Johnsen、2010年

2番目のリポジトリでは、ミラーリングはオプションではなくなったと思います(これにより、そもそも削除が発生した可能性があります)。
Craig Walker

回答:


102

私は専門家ではありません。しかし、あなたは試すことができます

git fsck --full --no-reflogs | grep commit

削除されたブランチのHEADコミットを見つけ、それらを取り戻すため。


以前にfsckを試しました。正しいコミットを見つける方法を知っていますか?私は試すために20を持っています。
Craig Walker

1
これで終わりました。コミットメッセージを受け取ったら、git branch <uid>それらを取り戻します。ありがとう!
Craig Walker

聞いてよかった。remotes.origin.mirrorremotes.origin.fetch設定の間の競合も必ず解決してください。そうしないと、問題が再び発生する可能性があります(または他のリポジトリから誤ってプッシュされてコミットが失敗する)。
Chris Johnsen、2010年

@Craig:参考になったことを
嬉しく思い

3
今日、リリース候補ブランチを失いました。コミットIDがわかりませんでした。次を使用して回復しました:git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
spezifanta

23

たった2つのコマンドで私の命を救う

1.これにより、以前のすべてのHEADが一覧表示されます

git reflog

2.これにより、HEADが元に戻り、削除したことが確定します。

git reset --hard <your deleted commit>
ex. git reset --hard b4b2c02

1
ローカルでブランチにチェックインしたことがないので、HEADがそこに行ったことがないため、でコミットIDを見つけることができませんgit reflog。他に試すことができるものはありますか?
zyy

1
@zyyと同じリモートで他のチームメンバーによってコミットが削除されたので、ローカルマシンにコミットを戻して(ローカルでコミットしたことがない)、プッシュバックする必要があります...
OmGanesh

11

削除されたブランチは失われず、表示されたフェッチによってorigin / contact_pageおよびorigin / new_picturesの「リモートトラッキングブランチ」にコピーされました(表示されたプッシュによってブランチもプッシュバックされましたが、refs / remotes /にプッシュされました) refs / heads /の代わりにorigin /)。チェックgit log origin/contact_pageしてgit log origin/new_pictures、あなたのローカルコピーは、あなたがそこにあるべきだと思うものは何でもして「最新」しているかどうかを確認します。表示されたフェッチとプッシュの間に新しいコミットがこれらのブランチに(他のリポジトリから)プッシュされた場合、それらを「失った」可能性があります(ただし、最後にそれらのブランチをプッシュした他のリポジトリでそれらを見つけることができるでしょう)。 。

フェッチ/プッシュの競合

通常の「リモートモード」でフェッチしているようですが(リモートrefs / heads /はローカルにrefs / remotes / origin /に保存されています)、「ミラーモード」でプッシュしています(ローカルrefs /はリモートrefs /にプッシュされています) 。.git / configを確認して、remote.origin.fetchremote.origin.push設定ます。

バックアップを作成

変更を試みる前に、単純なtarまたはzipアーカイブまたはローカルリポジトリ全体を作成します。そうすれば、何が起こるか気に入らない場合は、復元したリポジトリからもう一度試すことができます。

オプションA:ミラーとして再構成する

リモートリポジトリをローカルリポジトリのミラーとして使用する場合は、次のようにします。

git branch contact_page origin/contact_page &&
git branch new_pictures origin/new_pictures &&
git config remote.origin.fetch '+refs/*:refs/*' &&
git config --unset remote.origin.push &&
git config remote.origin.mirror true

refs / remotes / origin / refsは、ミラーモードで操作している場合は役に立たないため、最終的にはすべて削除することもできます(通常のブランチは通常のリモートトラッキングブランチの代わりになります)。

オプションB:通常のリモートとして再構成する

しかし、このリモートリポジトリを複数の「作業」リポジトリで使用しているように見えるため、おそらくミラーモードを使用する必要はありません。あなたはこれを試すかもしれません:

git config push.default tracking &&
git config --unset remote.origin.push
git config --unset remote.origin.mirror

次に、最終的にはリモートリポジトリ内の偽のrefs / remotes / origin refsを削除する必要がありますgit push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures …

テストプッシュ

リモートリポジトリに変更を加えなくても、何が行われるgit push --dry-runかを確認してくださいgit push。表示される内容が気に入らない場合は、バックアップ(tar / zip)から回復し、他のオプションを試してください。


1
リモートトラッキングブランチがコピーされたとしても、保持されていないと思います。'git branch -a'はそれらを表示せず、.git dirでもこれらの名前のファイルを見つけることができません。最後に、推奨する「git log」コマンドは「fatal:ambiguous argument 'origin / contact_page':unknown revision or path not not in the working tree」を返します:-\ありがとうございます。
Craig Walker

1
まあ、それらのブランチはそこにありました、あなたのプッシュログはそれを示しています。.gitディレクトリで参照を探す場合は、.git/packed_refsに加えて必ず確認してください.git/refs/git show-refすべてのローカル参照(パックまたは「ルーズ」)をダンプします。それでも、元のGitHubリポジトリにプッシュされた参照を(別のマシン上にある?他の誰かのリポジトリ?)見つけることができるはずです。失敗した場合は、GCまたはプルーニングを実行していない限り、git fsck出力を参照してダングリングコミットを調べ、再アタッチできますgit branch contact_page-recovered <SHA-1-of-dangling-commit>
Chris Johnsen、2010年

pack_refsにもありませんでした。コミットは間違いなくぶら下がっていました。それがどのように起こったかはわかりません。あなたの助けをありがとう!
Craig Walker、

8

削除が十分最近の場合(Oh-NO!の瞬間のように)、まだメッセージが表示されているはずです。

Deleted branch <branch name> (was abcdefghi).

あなたはまだ走ることができます:

git checkout abcdefghi

git checkout -b <some new branch name or the old one>


8
  1. coimmit IDを見つける

    git reflog

  2. 誤って削除したローカルブランチを復元する

    git branch need-recover-branch-name commitId

  3. 以前にもリモートブランチを削除した場合は、need-recover-branch-nameを再度プッシュします

    git push origin need-recover-branch-name


2
これでうまくいきました。それははるかに少ないステップだったので、私は受け入れられた答えよりも好みます。とgit reflog推測する必要はなく、からのコミットメッセージを見ることができましたgit show
theUtherSide

3

データはまだgithubに残っています。古いデータから新しいブランチを作成できます。

git checkout origin/BranchName #get a readonly pointer to the old branch
git checkout –b BranchName #create a new branch from the old
git push origin BranchName #publish the new branch

1

「フェッチ」と「プッシュ」の設定が一致していないと思います。これにより、デフォルトのフェッチ/プッシュが適切にラウンドトリップしなくなりました。幸い、後で削除したブランチをフェッチしたので、明示的なプッシュでブランチを再作成できるはずです。

git push origin origin/contact_page:contact_page origin/new_pictures:new_pictures

@Chris Johnsonへの私のコメントと同様に、ブランチはローカルに存在しない(存在しない)ようです。私はときにgit push origin origin/contact_page:contact_page私はこれを取得: error: src refspec origin/contact_page does not match any
クレイグ・ウォーカー

わかりました、何が起こったのかはわかります(ただし、完全なエラーは役に立ちます)。pushは削除されたブランチを更新し、ローカルで参照を削除しました。追跡参照でもあります。なんてgit rev-parse refs/remotes/origin/origin/contact_page言うの?偽の「ミラー」構成のため、ブランチはここでローカルリポジトリで参照されます。
CBベイリー

こんにちはチャールズ。これを書いたので、設定を変更(および修正)したため、(意味のある)rev-parse出力を取得できなくなりました。しかし、リモートに二重にネストされた「origin」ディレクトリがあったとは思いません。
Craig Walker

0

組織がJIRAまたはgitに関連付けられている別の同様のシステムを使用している場合、チケット自体にリストされているコミットを見つけて、コード変更へのリンクをクリックできます。Githubはブランチを削除しますが、まだチェリーピッキングに使用できるコミットがあります。


-1

慎重すぎるように見えるかもしれませんが、ソース管理に変更を加える前に、私が作業しているもののコピーを頻繁に圧縮します。私が取り組んでいるGitlabプロジェクトで、最近、誤ってリモートブランチを削除しましたが、マージリクエストをマージした後も残したいと思いました。コミット履歴を元に戻すために私がしなければならなかったのは、もう一度プッシュするだけでした。マージリクエストはまだGitlabによって追跡されているため、ブランチの右側に青い「マージ済み」ラベルが表示されます。何か問題が発生した場合に備えて、ローカルフォルダを圧縮しました。

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