Git menarik setelah pembaruan paksa

333

Saya hanya menekan beberapa komitmen dengan git rebasedan melakukan git push --force(yang jahat, saya tahu).

Sekarang insinyur perangkat lunak lain memiliki sejarah yang berbeda dan ketika mereka melakukan git pull, Git akan bergabung. Apakah ada cara untuk memperbaikinya, kecuali melakukan rm my-repo; git clone [email protected]:my-repo.git?

Saya butuh sesuatu seperti kebalikan dari git push --force, tetapi git pull --forcetidak memberikan hasil yang diinginkan.

iblue
sumber
16
mereka dapat menghapus cabang mereka dan membuatnya kembali juga, tanpa harus menghapus seluruh repo:git checkout master && git branch -D test && git checkout -b test origin/test
Florian Klein
1
Kemungkinan duplikat dari Force Git untuk menimpa file lokal di pull
gpoo

Jawaban:

511

Untuk menerima komitmen baru

git fetch

Setel ulang

Anda dapat mengatur ulang komit untuk cabang lokal menggunakan git reset.

Untuk mengubah komit dari cabang lokal:

git reset origin/master --hard

Berhati-hatilah, seperti yang dijelaskan dalam dokumentasi:

Atur ulang indeks dan pohon kerja. Setiap perubahan pada file yang dilacak di pohon kerja sejak <commit> dibuang.

Jika Anda ingin menyimpan perubahan apa pun yang Anda miliki secara lokal - lakukan --softreset. Yang akan memperbarui histori komit untuk cabang, tetapi tidak mengubah file apa pun di direktori kerja (dan Anda kemudian dapat mengkomitnya).

Rebase

Anda dapat memutar ulang komit lokal Anda di atas komit / cabang lain menggunakan git rebase:

git rebase -i origin/master

Ini akan meminta rebase dalam mode interaktif di mana Anda dapat memilih bagaimana menerapkan setiap komit yang tidak ada dalam riwayat yang Anda rebase di atas.

Jika komit yang Anda hapus (dengan git push -f) telah ditarik ke dalam sejarah lokal, komit tersebut akan didaftar sebagai komit yang akan diterapkan kembali - komit tersebut harus dihapus sebagai bagian dari rebase atau akan dimasukkan kembali ke dalam riwayat untuk cabang - dan muncul kembali dalam sejarah jarak jauh pada dorongan berikutnya.

Gunakan bantuan git command --helpuntuk detail dan contoh lebih lanjut tentang salah satu dari perintah di atas (atau lainnya).

AD7six
sumber
2
@iblue memilih antara kehilangan semua perubahan, menghapus riwayat komit tetapi mempertahankan perubahan file, atau mencoba menerapkan setiap komit di atas kepala baru. Opsi paling sederhana mungkin adalah soft reset.
AD7six
1
@iblue Ketika kolega Anda menggunakan `git reabse origin / master ', dan sementara itu, mereka sudah memiliki beberapa commit sebelumnya, git akan menulis komit Anda di belakang komit mereka.
Tim
6
Mungkin perlu disebutkan bahwa jika ini untuk cabang yang berbeda:git reset origin/otherbranch --hard
bmaupin
Jadi, untuk memperjelas, ini adalah baik : Opsi 1: reset --hard, atau Opsi 2: reset --soft+ rebase, kan?
PlasmaBinturong
2
@PlasmaBinturong No. git reset --soft origin/masterakan mengubah histori komit untuk mencocokkan perbedaan remote dan stage ke remote yang kemudian dikomit . Tidak perlu melakukan rebase dalam skenario itu (dan Anda akan dicegah melakukannya karena perubahan yang tidak dikomit) karena tidak ada perbedaan dalam sejarah komit. Kedua opsi diatur ulang atau rebase - bukan kombinasi keduanya. Silakan ajukan pertanyaan jika skenario Anda berbeda dari yang saya jawab di sini.
AD7six
16

Ini tidak akan memperbaiki cabang yang sudah memiliki kode yang tidak Anda inginkan di dalamnya (lihat di bawah untuk cara melakukannya), tetapi jika mereka telah menarik beberapa cabang dan sekarang ingin itu menjadi bersih (dan bukan "di depan" dari asal / beberapa cabang) maka Anda cukup:

git checkout some-branch   # where some-branch can be replaced by any other branch
git branch base-branch -D  # where base-branch is the one with the squashed commits
git checkout -b base-branch origin/base-branch  # recreating branch with correct commits

Catatan: Anda dapat menggabungkan semua ini dengan menempatkan && di antaranya

Note2: Florian menyebutkan ini dalam komentar, tetapi siapa yang membaca komentar ketika mencari jawaban?

Note3: Jika Anda memiliki cabang yang terkontaminasi, Anda dapat membuat yang baru berdasarkan "dumb branch" yang baru dan hanya memilih komit.

Ex:

git checkout feature-old  # some branch with the extra commits
git log                   # gives commits (write down the id of the ones you want)
git checkout base-branch  # after you have already cleaned your local copy of it as above
git checkout -b feature-new # make a new branch for your feature
git cherry-pick asdfasd   # where asdfasd is one of the commit ids you want
# repeat previous step for each commit id
git branch feature-old -D # delete the old branch

Sekarang fitur-baru adalah cabang Anda tanpa komitmen ekstra (mungkin buruk)!

Tom Prats
sumber
Inilah yang benar-benar saya inginkan. Seseorang mengubah cabang utama (karena Tuhan tahu apa alasannya) tetapi saya tidak punya perubahan lokal yang ingin saya lakukan atau apa pun. Jadi yang harus saya lakukan adalah menghapus cabang master lokal saya (yang terasa sangat aneh) dan melakukan checkout lagi. Terima kasih!
Danilo Carvalho
@ peter-mortensen Suntingan harus substansial sesuai dengan stackoverflow.com/help/editing
Tom Prats
untuk langkah terakhir, Anda juga bisa menggunakan git checkout -b base-branch origin/base-branchdengangit checkout --track origin/base-branch
bluesmonk
2

Tarik dengan rebase

Tarik reguler adalah mengambil + gabungan, tetapi yang Anda inginkan adalah mengambil + rebase. Ini adalah opsi dengan pullperintah:

git pull --rebase
herman
sumber
Saya menggunakan ini sepanjang waktu untuk mendapatkan kode terbaru dari master ke dalam cabang fitur saya tanpa harus menggabungkan semua komitmen dalam sejarah.
herman