Apa cara terbaik untuk membatalkan gabungan Git yang menghapus file dari repo?

13

Jadi bayangkan hal berikut terjadi (dan kita semua menggunakan SourceTree):

  1. Kita semua bekerja asal / berkembang.
  2. Saya pergi berlibur selama seminggu.
  3. Rekan kerja saya telah bekerja secara lokal selama beberapa hari terakhir tanpa menggabungkan asal / mengembangkan kembali ke cabang pengembangan lokalnya.
  4. Dia mencoba melakukan dorongan, diberitahu bahwa dia harus bergabung terlebih dahulu, dan kemudian melakukan tarikan.
  5. Dia mendapat konflik, menghentikan komit otomatis setelah penggabungan dari proses.
  6. Dengan asumsi bahwa Git seperti SVN, rekan kerja saya membuang file "baru" dalam copy pekerjaannya dan kemudian melakukan penggabungan - menghapus file "baru" dari kepala asal / kembangkan.
  7. Pekerjaan dev selama berminggu-minggu berlangsung di atas revisi itu.
  8. Saya kembali dari liburan dan mengetahui bahwa beberapa hari pekerjaan saya hilang.

Kami semua sangat baru di Git (ini adalah proyek pertama kami yang menggunakannya), tetapi yang saya lakukan untuk memperbaikinya adalah:

  1. Ganti nama "kembangkan" menjadi "develop_old".
  2. Gabungkan develop_old ke cabang baru "develop_new".
  3. Setel ulang cabang develop_new ke komit terakhir sebelum penggabungan buruk.
  4. Cherry memilih setiap komitmen sejak saat itu, satu per satu, menyelesaikan konflik dengan tangan.
  5. Dorong develop_old dan develop_new hingga ke titik asal.

Pada titik ini, develop_new adalah, saya berharap, salinan "baik" dari semua perubahan kami dengan minggu-minggu berikutnya kerja layak diterapkan kembali. Saya juga mengasumsikan bahwa "terbalik komit" akan melakukan hal-hal aneh di merge, terutama karena beberapa minggu ke depan senilai bekerja didasarkan pada itu - dan karena gabungan yang berisi banyak hal yang kita lakukan ingin bersama dengan barang-barang yang kita don' t.

Saya berharap ini tidak pernah terjadi lagi, tetapi jika itu terjadi lagi, saya ingin tahu cara yang lebih mudah / lebih baik untuk memperbaiki keadaan. Apakah ada cara yang lebih baik untuk membatalkan penggabungan "buruk", ketika banyak pekerjaan telah dilakukan di repo berdasarkan penggabungan itu?

George
sumber
1
Bisakah Anda memposting tangkapan layar pohon git (disunting dengan tepat) atau output dari git logformat favorit Anda dengan anotasi yang sesuai tentang apa yang terjadi di berbagai commit? (Saya akan menghapus / membubuhi keterangan git log --graph --pretty=oneline --abbrev-commitdan pergi dari sana)
1
Sudah terlambat untuk Anda, tetapi unit test akan menangkapnya.
nalply
1
@nalply: Tidak jika gabungan buruk juga menghapus tes unit.
Aaronaught
Wow, itu nasib buruk yang berbahaya.
nalply

Jawaban:

6

Jika saya mengerti dengan benar, ini adalah situasi Anda:

    ,-c--c--c--c--M--a--a--X ← develop
o--o--y--y--y--y-´

Setelah beberapa sejarah umum (o), Anda berkomitmen dan mendorong pekerjaan Anda (y). Rekan kerja Anda (c) berhasil di repositori lokalnya dan melakukan penggabungan yang buruk (M). Setelah itu mungkin ada beberapa komitmen tambahan (a) di atas M.

git reset --hard develop M^2
git branch coworker M^1

Sekarang grafik Anda terlihat persis seperti sebelum penggabungan buruk:

    ,-c--c--c--c ← coworker
o--o--y--y--y--y ← develop

Lakukan penggabungan yang baik (G):

git checkout develop
git merge coworker

Yang menghasilkan:

    ,-c--c--c--c-、
o--o--y--y--y--y--G ← develop

Sekarang transplantasikan komitmen tambahan:

git reset --hard X
git rebase --onto G M develop

Ini memberikan hasil akhir:

    ,-c--c--c--c-、
o--o--y--y--y--y--G--a--a--X ← develop

Ketahuilah bahwa ini dapat menyebabkan lebih banyak konflik gabungan. Anda juga baru saja mengubah riwayat, yaitu semua rekan kerja Anda harus mengkloning / reset / rebase ke riwayat baru.

PS: tentu saja Anda harus mengganti G, Mdan Xdalam perintah Anda dengan id komit yang sesuai.

michas
sumber
Tampaknya cukup jelas dalam pertanyaan bahwa semua komitmen ini telah didorong ke repositori bersama, jadi saya tidak berpikir rebasing adalah pilihan yang baik. Mengembalikan semua komitmen baru-baru ini dan kemudian memetik ceri yang non-konflik di atas penggabungan yang baik lebih aman.
Aaronaught
Itu adalah bagian dengan klon / reset / rebase. - Jika hanya ada beberapa pengembang, memberi tahu mereka untuk memperbarui repositori mereka mungkin merupakan opsi yang valid.
michas
1

Ada baiknya Anda berpikir tentang cara memperbaiki repositori, tetapi jika rekan kerja Anda hanya menghapus file baru dan tidak menimpa banyak pembaruan, maka pendekatan yang jauh lebih sederhana adalah dengan hanya mengembalikan file yang telah dihapus.

Saya mungkin akan mulai dengan mencoba hanya mengambil ceri (ke kepala saat ini) komit asli di mana Anda menambahkan kode yang sekarang hilang. Jika karena alasan apa pun itu tidak berhasil, cukup periksa revisi lama dengan file yang Anda tambahkan, dan tambahkan kembali dalam komit baru.

Apa yang Anda gambarkan sebenarnya adalah subset dari anti-pola Git yang terkenal, yang bagi saya seumur hidup saya tidak dapat mengingat nama - tetapi intinya adalah, membuat "pengeditan manual" selama penggabungan Git (yaitu pengeditan) yang tidak benar-benar menyelesaikan konflik penggabungan tetapi membuat beberapa perubahan yang sama sekali tidak terkait) dianggap sebagai praktik yang sangat buruk karena mereka pada dasarnya ditutupi oleh gabungan itu sendiri, dan mudah diabaikan dalam tinjauan kode atau sesi debugging.

Jadi jelaskan kepada rekan kerja Anda bahwa ini adalah epik yang gagal, tetapi pertimbangkan menampar bantuan band sebelum bersiap untuk operasi besar.

Aaronaught
sumber
Saya setuju, jika seluruh keseluruhan file hilang satu hal yang dapat Anda lakukan adalah ini jika Anda tidak peduli tentang sejarah di file lama: 1.membuat cabang baru dari cabang yang saat ini kacau. 2. beralih ke cabang buruk dan buat cabang baru lain yang merupakan cabang penyelamat Anda 3. Dari cabang penyelamatan Anda kembali ke komit sebelum komit gagal. 4. Salin file yang dihapus di suatu tempat di luar git 5. Beralih ke cabang baru lainnya. 6. Salin versi baru dari file yang dihapus ke cabang baru dan komit. Ada cara yang lebih rumit yang menyelamatkan sejarah yang merupakan pos terkenal oleh Linus T.
Elin
1
Sebenarnya ini menunjukkan bagaimana Anda dapat menggunakan checkout jasonrudolph.com/blog/2009/02/25/… Itu jauh lebih baik.
Elin