Jawaban singkat
Anda menghilangkan fakta bahwa Anda berlari git push
, mendapatkan kesalahan berikut, dan kemudian melanjutkan untuk menjalankan git pull
:
To git@bitbucket.org:username/test1.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Meskipun Git berusaha membantu, saran 'git pull' yang dimilikinya kemungkinan besar bukanlah yang ingin Anda lakukan .
Jika Anda:
- Bekerja pada "cabang fitur" atau "cabang pengembang" saja , lalu Anda dapat menjalankan
git push --force
untuk memperbarui remote dengan komitmen pasca-rebase Anda ( sesuai jawaban pengguna4405677 ).
- Bekerja pada cabang dengan banyak pengembang pada saat yang sama, maka Anda mungkin tidak boleh menggunakannya
git rebase
sejak awal. Untuk memperbarui dev
dengan perubahan dari master
, Anda harus, alih-alih menjalankan git rebase master dev
, jalankan git merge master
saat di dev
( sesuai jawaban Justin ).
Penjelasan yang sedikit lebih panjang
Setiap hash komit di Git didasarkan pada sejumlah faktor, salah satunya adalah hash komit yang ada sebelumnya.
Jika Anda menyusun ulang komit, Anda akan mengubah hash komit; rebasing (ketika melakukan sesuatu) akan mengubah hash komit. Dengan itu, hasil dari menjalankan git rebase master dev
, di mana dev
tidak sinkron dengan master
, akan membuat komit baru (dan dengan demikian hash) dengan konten yang sama seperti yang ada dev
tetapi dengan komit pada yang master
disisipkan sebelumnya.
Anda bisa berakhir dalam situasi seperti ini dengan berbagai cara. Dua cara yang bisa saya pikirkan:
- Anda dapat memiliki komitmen
master
yang Anda inginkan sebagai dasar dev
pekerjaan Anda
- Anda bisa saja komit
dev
yang telah didorong ke remote, yang kemudian Anda ubah (reword komit pesan, susun ulang komit, komit squash, dll.)
Mari kita lebih memahami apa yang terjadi — berikut ini contohnya:
Anda memiliki repositori:
2a2e220 (HEAD, master) C5
ab1bda4 C4
3cb46a9 C3
85f59ab C2
4516164 C1
0e783a3 C0
Anda kemudian melanjutkan untuk mengubah komit.
git rebase --interactive HEAD~3 # Three commits before where HEAD is pointing
(Di sinilah Anda harus mengambil kata-kata saya: ada sejumlah cara untuk mengubah komit di Git. Dalam contoh ini saya mengubah waktunya C3
, tetapi Anda memasukkan komit baru, mengubah pesan komit, menyusun ulang komit, meremas komitmen bersama, dll.)
ba7688a (HEAD, master) C5
44085d5 C4
961390d C3
85f59ab C2
4516164 C1
0e783a3 C0
Di sinilah penting untuk diperhatikan bahwa hash komit berbeda. Ini adalah perilaku yang diharapkan karena Anda telah mengubah sesuatu (apa pun) tentang mereka. Ini tidak masalah, TAPI:
Mencoba mendorong akan menunjukkan kesalahan (dan petunjuk bahwa Anda harus lari git pull
).
$ git push origin master
To git@bitbucket.org:username/test1.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:username/test1.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Jika kita jalankan git pull
, kita melihat log ini:
7df65f2 (HEAD, master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 (origin/master) C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
Atau, ditunjukkan dengan cara lain:
Dan sekarang kami memiliki komitmen ganda secara lokal. Jika kami menjalankannya, git push
kami akan mengirimnya ke server.
Untuk menghindari sampai ke tahap ini, kita bisa saja lari git push --force
(di mana kita malah lari git pull
). Ini akan mengirimkan komit kami dengan hash baru ke server tanpa masalah. Untuk memperbaiki masalah pada tahap ini, kami dapat mengatur ulang kembali ke sebelum kami menjalankan git pull
:
Lihatlah reflog ( git reflog
) untuk melihat apa hash komit itu sebelum kita berlari git pull
.
070e71d HEAD@{1}: pull: Merge made by the 'recursive' strategy.
ba7688a HEAD@{2}: rebase -i (finish): returning to refs/heads/master
ba7688a HEAD@{3}: rebase -i (pick): C5
44085d5 HEAD@{4}: rebase -i (pick): C4
961390d HEAD@{5}: commit (amend): C3
3cb46a9 HEAD@{6}: cherry-pick: fast-forward
85f59ab HEAD@{7}: rebase -i (start): checkout HEAD~~~
2a2e220 HEAD@{8}: rebase -i (finish): returning to refs/heads/master
2a2e220 HEAD@{9}: rebase -i (start): checkout refs/remotes/origin/master
2a2e220 HEAD@{10}: commit: C5
ab1bda4 HEAD@{11}: commit: C4
3cb46a9 HEAD@{12}: commit: C3
85f59ab HEAD@{13}: commit: C2
4516164 HEAD@{14}: commit: C1
0e783a3 HEAD@{15}: commit (initial): C0
Di atas kami melihat bahwa ba7688a
kami berkomitmen sebelum berlari git pull
. Dengan hash komit di tangan kita dapat mengatur ulang kembali ke itu ( git reset --hard ba7688a
) dan kemudian menjalankan git push --force
.
Dan kami selesai.
Tapi tunggu, saya terus mendasarkan pekerjaan dari komit yang digandakan
Jika Anda entah bagaimana tidak menyadari bahwa komit diduplikasi dan terus bekerja di atas komit duplikat, Anda benar-benar telah membuat kekacauan untuk diri Anda sendiri. Ukuran kekacauan sebanding dengan jumlah komitmen yang Anda miliki di atas duplikat.
Seperti apa ini:
3b959b4 (HEAD, master) C10
8f84379 C9
0110e93 C8
6c4a525 C7
630e7b4 C6
070e71d (origin/master) Merge branch 'master' of bitbucket.org:username/test1
ba7688a C5
44085d5 C4
961390d C3
2a2e220 C5
85f59ab C2
ab1bda4 C4
4516164 C1
3cb46a9 C3
0e783a3 C0
Atau, ditunjukkan dengan cara lain:
Dalam skenario ini kami ingin menghapus komit duplikat, tetapi tetap mempertahankan komitmen yang telah kami lakukan berdasarkan komitmen tersebut — kami ingin mempertahankan C6 hingga C10. Seperti kebanyakan hal, ada beberapa cara untuk melakukannya:
Antara:
- Buat cabang baru di komit 1 duplikat terakhir ,
cherry-pick
masing-masing komit (termasuk C6 hingga C10) ke cabang baru itu, dan perlakukan cabang baru itu sebagai kanonik.
- Jalankan
git rebase --interactive $commit
, di mana $commit
komit sebelum kedua komit yang digandakan 2 . Di sini kita bisa langsung menghapus garis untuk duplikat.
1 Tidak masalah mana yang Anda pilih, salah satu ba7688a
atau 2a2e220
berfungsi dengan baik.
2 Dalam contoh itu akan 85f59ab
.
TL; DR
Setel advice.pushNonFastForward
ke false
:
git config --global advice.pushNonFastForward false