Git: กู้คืนสาขาที่ถูกลบ (ระยะไกล)


95

ฉันต้องการกู้คืนสาขา Git สองสาขาที่ฉันลบไปในระหว่างการพุช

สองสาขานี้ถูกสร้างขึ้นในระบบที่แตกต่างกันจากนั้นจึงพุชไปยังที่เก็บ "shared" (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

หลังจากนั้นฉันก็ส่งการเปลี่ยนแปลงในพื้นที่ของฉันไปยัง repo ส่วนกลาง ด้วยเหตุผลบางประการสาขาเหล่านี้จึงถูกลบออกจากทั้งระบบภายในและ repo ส่วนกลางของฉัน:

~/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

มันไม่ใช่เรื่องง่ายเลยที่จะเอากิ่งไม้ออกจากเครื่องกำเนิดของมันดังนั้นฉันจึงอยากลองกู้คืนจากท้องถิ่นของฉันถ้าเป็นไปได้

ข้อมูลคอมไพล์ "เลิกทำ" ทั้งหมดที่กูเกิลต้องทำกับการกู้คืนคอมมิตที่เสียไป ฉันไม่คิดว่าจะใช้ได้กับที่นี่เนื่องจากฉันไม่ได้ผูกมัด UID สำหรับสาขาเหล่านี้

ฉันอยากรู้ว่าฉันจะเอาสิ่งเหล่านี้กลับคืนมาได้อย่างไร ฉันอยากรู้ด้วยว่าพวกเขาถูกลบไปตั้งแต่แรกอย่างไรและฉันจะหลีกเลี่ยงปัญหานี้ได้อย่างไรในอนาคต

แก้ไข: ตามคำขอนี่คือการกำหนดค่า repo ของฉัน

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 Bailey

ค่อนข้างเป็นไปได้; ผมเคยโพสต์ไว้
Craig Walker

2
คุณremote.origin.fetchrefspec remote.origin.mirror = trueไม่เหมาะสมสำหรับการใช้งานกับ คุณต้องการมิเรอร์หรือคุณต้องการใช้ GitHub repo เป็นรีโมทธรรมดาหรือไม่? คำตอบของฉันควรมีคำสั่งที่คุณต้องการไม่ว่าจะด้วยวิธีใดก็ตาม
Chris Johnsen

ฉันเดาว่าด้วยที่เก็บที่ 2 การมิเรอร์ไม่ใช่ตัวเลือกอีกต่อไป (อาจทำให้เกิดการลบตั้งแต่แรก)
Craig Walker

คำตอบ:


103

ฉันไม่ใช่ผู้เชี่ยวชาญ แต่คุณสามารถลอง

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

เพื่อค้นหาการคอมมิต HEAD ของสาขาที่ถูกลบและเรียกคืน


ฉันลอง fsck ก่อนหน้านี้ คุณรู้วิธีค้นหาว่าการกระทำใดที่ถูกต้อง? ฉันมี 20 ให้ลอง
Craig Walker

1
สิ่งนี้ทำได้; เมื่อฉันมีข้อความคอมมิตแล้วgit branch <uid>ให้ส่งกลับ ขอบคุณ!
Craig Walker

ดีใจที่ได้ยิน. อย่าลืมแก้ไขข้อขัดแย้งระหว่างการตั้งค่าremotes.origin.mirrorและremotes.origin.fetchการตั้งค่าของคุณด้วยมิฉะนั้นคุณจะต้องพบกับปัญหาอีกครั้ง (หรือการกระทำของ clobber โดยไม่ได้ตั้งใจที่ถูกผลักจาก repos อื่น)
Chris Johnsen

@ Craig: ดีใจที่มีประโยชน์ :)
iamamac

3
ฉันสูญเสียสาขาผู้สมัครที่ได้รับการปล่อยตัวในวันนี้ ไม่ทราบรหัสการกระทำ กู้คืนได้โดยใช้:git fsck --full --no-reflogs | cut -d' ' -f3 | xargs -P8 git log --oneline | grep 'Release 2.60.0.157'
spezifanta

23

คำสั่งเพียงสองคำช่วยชีวิตฉัน

1. นี่จะแสดงรายการ HEAD ก่อนหน้าทั้งหมด

git reflog

2. สิ่งนี้จะย้อนกลับ HEAD เพื่อยืนยันว่าคุณลบไปแล้ว

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

1
git reflogฉันไม่เคยตรวจสอบในสาขาเฉพาะเพื่อให้หัวของฉันไม่เคยได้รับมีดังนั้นฉันไม่สามารถหาสิ่งที่กระทำกับ ID มีอะไรให้ลองอีกไหม?
zyy

1
เหมือนกับ @zyy การคอมมิตถูกลบโดยสมาชิกในทีมคนอื่นในระยะไกลดังนั้นฉันจึงต้องนำมันกลับมาในเครื่องของฉัน (ฉันไม่เคยมีคอมมิตในเครื่อง) และผลักกลับ ...
OmGanesh

11

สาขาที่ถูกลบของคุณจะไม่สูญหายสาขาเหล่านั้นจะถูกคัดลอกไปยังต้นทาง / contact_pageและต้นทาง / new_pictures "สาขาการติดตามระยะไกล" โดยการดึงข้อมูลที่คุณแสดง (พวกมันถูกผลักกลับออกไปด้วยการผลักดันที่คุณแสดง แต่พวกมันถูกส่งไปยัง refs / remotes / ต้นกำเนิด / แทนการอ้างอิง / หัว /) ตรวจสอบgit log origin/contact_pageและgit log origin/new_picturesดูว่าสำเนาในเครื่องของคุณ "ทันสมัย" หรือไม่สำหรับสิ่งที่คุณคิดว่าควรจะมี หากการกระทำใหม่ใด ๆ ถูกผลักไปยังสาขาเหล่านั้น (จาก repo อื่น ๆ ) ระหว่างการดึงข้อมูลและการผลักดันที่คุณแสดงคุณอาจ "แพ้" สิ่งเหล่านั้น (แต่คุณอาจพบได้ใน repo อื่นที่เพิ่งผลักดันสาขาเหล่านั้น) .

ดึง / ผลักดันความขัดแย้ง

ดูเหมือนว่าคุณกำลังดึงข้อมูลใน 'โหมดระยะไกล' ปกติ (การอ้างอิงระยะไกล / หัว / ถูกเก็บไว้ในเครื่องในการอ้างอิง / รีโมท / จุดเริ่มต้น /) แต่การผลักดันใน 'โหมดมิเรอร์' (การอ้างอิงในพื้นที่ / ถูกผลักไปยังการอ้างอิงระยะไกล /) . ตรวจสอบ. git / config ของคุณและกระทบยอดremote.origin.fetchและremote.origin.pushการตั้งค่า

ทำการสำรองข้อมูล

ก่อนที่จะลองเปลี่ยนแปลงใด ๆ ให้สร้างไฟล์ tar หรือ zip อย่างง่ายหรือ repo ในเครื่องของคุณทั้งหมด ด้วยวิธีนี้หากคุณไม่ชอบสิ่งที่เกิดขึ้นคุณสามารถลองอีกครั้งจาก repo ที่กู้คืนได้

ตัวเลือก A: กำหนดค่าใหม่เป็นมิเรอร์

หากคุณตั้งใจจะใช้ repo ระยะไกลของคุณเป็นมิเรอร์ของท้องถิ่นของคุณให้ทำสิ่งนี้:

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: กำหนดค่าใหม่เป็นรีโมทปกติ

แต่เนื่องจากดูเหมือนว่าคุณกำลังใช้ repo ระยะไกลนี้กับ repos "ที่ทำงาน" หลายรายการคุณอาจไม่ต้องการใช้โหมดมิเรอร์ คุณอาจลองทำสิ่งนี้:

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

จากนั้นคุณก็จะต้องการลบปลอม refs / รีโมท / refs กำเนิดใน repo git push origin :refs/remotes/origin/contact_page :refs/remotes/origin/new_pictures …ระยะไกลของคุณ:

ทดสอบ Push

ลองgit push --dry-runดูว่าgit pushจะทำอย่างไรโดยไม่ต้องทำการเปลี่ยนแปลงใด ๆ ใน repo ระยะไกล หากคุณไม่ชอบสิ่งที่ระบุให้กู้คืนจากข้อมูลสำรอง (tar / zip) แล้วลองใช้ตัวเลือกอื่น


1
ฉันไม่คิดว่าสาขาการติดตามระยะไกลจะถูกเก็บไว้หากมีการคัดลอกเลย 'git branch -a' ไม่แสดงและฉันไม่พบไฟล์ใด ๆ ที่มีชื่อเหล่านั้นใน. git dir ด้วย สุดท้ายคำสั่ง "git log" ที่คุณแนะนำส่งคืน "fatal: ambiguous อาร์กิวเมนต์" origin / contact_page ": การแก้ไขที่ไม่รู้จักหรือเส้นทางที่ไม่อยู่ในโครงสร้างการทำงาน": - \ ขอบคุณ
Craig Walker

1
สาขาเหล่านั้นอยู่ที่นั่นบันทึกการพุชของคุณจะแสดงให้เห็น เมื่อมองหา refs ใน.gitdir ให้แน่ใจว่าได้ตรวจสอบนอกเหนือไปจาก.git/packed_refs จะทิ้งการอ้างอิงในพื้นที่ของคุณทั้งหมด (บรรจุหรือ 'หลวม') คุณควรจะยังสามารถค้นหาการอ้างอิงใน repo ที่เดิมผลักดันพวกเขาไปยังที่เก็บ GitHub ของคุณ (บนเครื่องอื่น repo ของคนอื่น?) ความล้มเหลวที่ตราบใดที่คุณยังไม่ได้ทำ GC หรือลูกพรุน, คุณควรจะสามารถที่จะส่งออกไปตรวจสอบกระทำห้อยและใส่กลับเข้าไปพวกเขา .git/refs/git show-refgit fsckgit branch contact_page-recovered <SHA-1-of-dangling-commit>
Chris Johnsen

pack_refs ก็ไม่มีเช่นกัน การกระทำนั้นห้อยลงอย่างแน่นอน ไม่รู้ว่ามันเกิดขึ้นได้อย่างไร ขอบคุณสำหรับความช่วยเหลือของคุณ!
Craig Walker

8

หากการลบล่าสุดเพียงพอ (Like an Oh-NO! moment) คุณควรจะยังคงมีข้อความ:

Deleted branch <branch name> (was abcdefghi).

คุณยังสามารถเรียกใช้:

git checkout abcdefghi

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


8
  1. ค้นหารหัส coimmit

    git reflog

  2. กู้คืนสาขาในพื้นที่ที่คุณลบโดยไม่ได้ตั้งใจ

    git branch need-recover-branch-name commitId

  3. กด need-recover-branch-name อีกครั้งหากคุณลบ remote branch ก่อน

    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
Craig Walker

ตกลงฉันคิดว่าฉันเห็นสิ่งที่เกิดขึ้น (แม้ว่าข้อผิดพลาดทั้งหมดจะเป็นประโยชน์ก็ตาม) push ได้อัปเดตสาขาที่ถูกลบและลบการอ้างอิงในเครื่องรวมถึงการอ้างอิงการติดตาม อะไรgit rev-parse refs/remotes/origin/origin/contact_pageเอ่ย? เนื่องจากการกำหนดค่า 'มิเรอร์' ปลอมตอนนี้สาขาของฉันถูกอ้างถึงที่นี่ในที่เก็บท้องถิ่น
CB Bailey

สวัสดีชาร์ลส์; เนื่องจากฉันเขียนสิ่งนี้ฉันได้ munged (และแก้ไข) config ของฉันดังนั้นฉันจึงไม่สามารถรับเอาต์พุตการแยกวิเคราะห์ rev (meaninful) อีก อย่างไรก็ตามฉันไม่คิดว่ามีไดเร็กทอรี "origin" ที่ซ้อนกันสองครั้งในรีโมต
Craig Walker

0

หากองค์กรของคุณใช้ JIRA หรือระบบอื่นที่คล้ายกันที่เชื่อมโยงกับคอมไพล์คุณสามารถค้นหาคอมมิตที่ระบุไว้ในทิกเก็ตและคลิกลิงก์เพื่อเปลี่ยนโค้ด Github ลบสาขา แต่ยังมีคอมมิตสำหรับเก็บเชอร์รี่


-1

มันอาจจะดูระมัดระวังเกินไป แต่ฉันมักจะซิปสำเนาของสิ่งที่ฉันกำลังทำอยู่ก่อนที่ฉันจะทำการเปลี่ยนแปลงการควบคุมแหล่งที่มา ในโครงการ Gitlab ที่ฉันกำลังทำอยู่ฉันเพิ่งลบสาขาระยะไกลโดยไม่ได้ตั้งใจซึ่งฉันต้องการเก็บไว้หลังจากรวมคำขอรวม ปรากฎว่าทั้งหมดที่ฉันต้องทำเพื่อให้มันกลับมาพร้อมกับประวัติการกระทำก็ถูกผลักดันอีกครั้ง Gitlab ยังคงติดตามคำขอผสานดังนั้นจึงยังคงแสดงป้ายกำกับ "ผสาน" สีฟ้าที่ด้านขวาของสาขา ฉันยังคงบีบอัดโฟลเดอร์ในเครื่องของฉันไว้เผื่อว่าจะมีอะไรไม่ดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.