Bagaimana menyelesaikan konflik simpanan git tanpa komit?

495

Seperti yang ditanyakan dalam pertanyaan ini , saya juga ingin tahu bagaimana menyelesaikan konflik git stash poptanpa menambahkan semua modifikasi ke komit (seperti "git stash pop" tanpa konflik tidak).

Pendekatan saya saat ini sangat tidak keren karena saya melakukannya dengan cara ini:

git stash pop -> CONFLICT
git stash drop
[resolve conflict]
[add conflict files]
git reset HEAD <all files that are in commit-mode>

[Perbarui] Cara memperbanyaknya:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27: Menambahkan file baru yang disebut 'ketiga' ke contoh untuk menunjukkan bahwa solusi seperti scy hanya bekerja untuk HEADs kosong tetapi tidak memperbaiki masalah awal bahwa HEAD tidak memiliki konten yang sama seperti untuk git stash poptanpa konflik.

Sven
sumber
Jadi Anda git addfile konflik yang Anda selesaikan, secara efektif mengaturnya dalam indeks, dan Anda ingin tidak memilikinya dalam indeks kami?
Romain
Ya itu betul. Saya hanya ingin perilaku yang git stash popterjadi ketika tidak ada konflik (tetapi dengan pemberitahuan file mana yang perlu digabung).
Sven
2
Sepertinya jawaban untuk ini ada di sini: stackoverflow.com/questions/3945826/git-stash-questions . Dalam jawaban yang dipilih, pada komentar ke-4, Adam menjelaskan mengapa git melakukan ini.
Patrick
@ Patrick Terima kasih atas informasi ini - jadi sepertinya tidak akan ada solusi karena "desainnya"
Sven

Jawaban:

510

Jangan ikuti jawaban lain

Nah, Anda bisa mengikuti mereka :). Tetapi saya tidak berpikir bahwa melakukan komit dan mengatur ulang cabang untuk menghapus komit itu dan solusi serupa yang disarankan dalam jawaban lain adalah cara bersih untuk menyelesaikan masalah ini.

Solusi bersih

Solusi berikut ini tampaknya jauh lebih bersih bagi saya dan itu juga disarankan oleh Git sendiri - coba jalankan git statusdalam repositori dengan konflik:

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Jadi mari kita lakukan apa yang disarankan Git (tanpa melakukan komitmen yang tidak berguna):

  1. Secara manual (atau menggunakan beberapa alat gabungan , lihat di bawah) menyelesaikan konflik.
  2. Gunakan git resetuntuk menandai konflik sebagai terselesaikan dan menghapus tahapan perubahan. Anda dapat menjalankannya tanpa parameter apa pun dan Git akan menghapus semuanya dari indeks. Anda tidak harus mengeksekusi git addsebelumnya.
  3. Akhirnya, hapus simpanan dengan git stash drop, karena Git tidak melakukan itu pada konflik.

Diterjemahkan ke baris perintah:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

Penjelasan tentang perilaku default

Ada dua cara untuk menandai konflik yang diselesaikan: git adddan git reset. Sementara git resetmenandai konflik sebagai terselesaikan dan menghapus file dari indeks, git addjuga menandai konflik sebagai diselesaikan, tetapi menyimpan file dalam indeks.

Menambahkan file ke indeks setelah konflik diselesaikan dengan sengaja. Dengan cara ini Anda dapat membedakan perubahan dari simpanan sebelumnya dan perubahan yang Anda buat setelah konflik diselesaikan. Jika Anda tidak menyukainya, Anda selalu dapat menggunakan git resetuntuk menghapus semuanya dari indeks.

Gabungkan alat

Saya sangat merekomendasikan menggunakan alat penggabungan 3 arah untuk menyelesaikan konflik, misalnya KDiff3 , Meld , dll., Daripada melakukannya secara manual. Biasanya menyelesaikan semua atau sebagian besar konflik secara otomatis. Ini penghemat waktu yang sangat besar !

David Ferenczy Rogožan
sumber
32
@ kalampal sepertinya dibutuhkan saat git stash popgagal dengan konflik.
Emile Bergeron
21
@ kalampal ya, Git bahkan memberi tahu Anda bahwa simpanan belum dijatuhkan jika terjadi konflik. Dan pertanyaannya adalah tentang kasus seperti itu, jadi Anda benar-benar perlu mengeksekusigit stash drop kecuali Anda ingin menyimpan simpanan itu.
David Ferenczy Rogožan
@ DavidFerenczyRogožan Git tidak memberi tahu saya sama sekali bahwa itu tidak menghapus entri simpanan. Versi 2.17.1 di sini.
Robert Siemer
298

Misalkan Anda memiliki skenario ini di mana Anda menyimpan perubahan Anda untuk menarik dari asal. Mungkin karena perubahan lokal Anda hanya debug: truedi beberapa file pengaturan. Sekarang Anda menarik dan seseorang telah memperkenalkan pengaturan baru di sana, menciptakan konflik.

git status mengatakan:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Baik. Saya memutuskan untuk pergi dengan apa yang disarankan Git: Saya menyelesaikan konflik dan berkomitmen:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Sekarang copy pekerjaan saya dalam keadaan yang saya inginkan, tetapi saya telah membuat komit yang tidak saya inginkan. Bagaimana cara saya menghilangkan komit itu tanpa memodifikasi copy pekerjaan saya? Tunggu, ada perintah populer untuk itu!

git reset HEAD^

Salinan kerja saya belum diubah, tetapi komit WIP hilang. Itulah yang saya inginkan! (Perhatikan bahwa saya tidak menggunakan di --softsini, karena jika ada file yang digabungkan secara otomatis di simpanan Anda, mereka dipentaskan secara otomatis dan dengan demikian Anda akan berakhir dengan file-file ini dipentaskan lagi setelah itu reset.)

Tapi ada satu hal lagi yang tersisa: Halaman manual untuk git stash popmengingatkan kita bahwa "Menerapkan negara dapat gagal dengan konflik; dalam hal ini, itu tidak dihapus dari daftar simpanan. Anda perlu menyelesaikan konflik dengan tangan dan menelepon git stash dropsecara manual setelah itu." Jadi itulah yang kami lakukan sekarang:

git stash drop

Dan selesai.

scy
sumber
34
Hanya ada banyak keburukan warisan dengan sengaja harus melakukan commit reset HEAD ^ ... untuk sesuatu yang seharusnya hanya memengaruhi pohon yang bekerja.
6
Mengapa tidak menyelesaikan saja konflik dan kemudian git add <resolved conflict files>diikuti git reset HEAD?
BoltzmannBrain
Terima kasih atas sarannya tetapi ini tidak memperbaiki masalah awal bahwa ini bukan perilaku yang sama seperti git stash poptanpa konflik. Cukup tambahkan file lain ke KEPALA sebelum melakukan konflik git stash popdan daripada Anda git commit -a -m WIPjuga akan menambahkan file baru ke komit. Tetapi tanpa konflik, hanya file baru akan tetap di HEAD tetapi tidak git stash popfile.
Sven
7
Saya tidak berpikir itu perlu untuk melakukan terlebih dahulu kemudian membatalkan melakukan. Cukup reset dari Dawid Ferenczy jawaban akan melakukan hal yang sama
vladkras
3
Untuk pengguna windows, ^digunakan sebagai kelanjutan garis khusus dan akan membuat Anda duduk di More? meminta alih-alih mengeksekusi perintah. Sebaliknya menggunakan: git reset --soft HEAD~1. Lihat bagaimana-do-i-delete-unpushed-git-commit?
mrfelis
87

Alih-alih menambahkan perubahan yang Anda buat untuk menyelesaikan konflik, Anda dapat menggunakan git reset HEAD fileuntuk menyelesaikan konflik tanpa melakukan perubahan.

Anda mungkin harus menjalankan perintah ini dua kali. Sekali untuk menandai konflik sebagai terselesaikan dan sekali untuk unstage perubahan yang dipentaskan oleh rutin resolusi konflik.

Ada kemungkinan bahwa harus ada mode reset yang melakukan kedua hal ini secara bersamaan, meskipun tidak ada sekarang.

ComputerDruid
sumber
2
Mode reset adalah yang saya cari - solusi lain seperti yang saya jelaskan dan tidak praktis untuk lebih dari 5 file.
Sven
25
Dan gunakan "git stash drop" setelahnya untuk menyelesaikan "git stash pop".
David Liu
2
Meskipun pertanyaan tidak menanyakan hal ini secara eksplisit, mungkin berguna untuk memperbarui jawaban dengan menyertakan "git stash drop" karena simpanan tidak dijatuhkan secara otomatis jika terjadi konflik.
Abhishek Pathak
29
git checkout stash -- .

bekerja untukku.

Catatan : ini bisa berbahaya karena tidak mencoba menggabungkan perubahan dari simpanan ke dalam copy pekerjaan Anda, tetapi menimpanya dengan file simpanan sebagai gantinya. Jadi, Anda dapat kehilangan perubahan yang tidak dikomit.

stevenspiel
sumber
Ini membantu ketika "git pull --autostash" memperkenalkan komitmen gabungan yang tidak diinginkan dan git checkout simpanan -. tanpa syarat menimpa konflik dari simpanan
Alec Istomin
11
git add .
git reset

git add . akan menampilkan SEMUA file yang memberitahu git bahwa Anda telah menyelesaikan konflik

git reset akan menghapus semua SEMUA file yang dipentaskan tanpa membuat komit

Aaron Goldman
sumber
Ini sebenarnya bukan jawaban yang buruk, itu cukup banyak seperti git add -uitugit reset
ebob
4

Sepertinya ini mungkin jawaban yang Anda cari, saya belum mencoba ini secara pribadi, tetapi sepertinya itu bisa melakukan trik. Dengan perintah ini, GIT akan mencoba menerapkan perubahan seperti sebelumnya, tanpa mencoba menambahkan semuanya untuk komit.

git stash apply --index

berikut ini penjelasan lengkapnya:

http://git-scm.com/book/en/Git-Tools-Stashing

Marco Ponti
sumber
Terima kasih atas petunjuk ini, tetapi ini tidak akan membantu ketika saya sudah melakukannya git stash pop- atau adakah cara untuk mengembalikan ini dan melakukan git stash apply --indexketika saya tahu itu git stash popakan mengalami konflik?
Sven
Saya telah menambahkan contoh tentang cara menghasilkan ini - bayangkan Anda mengedit lebih dari 10 file, jadi Anda tidak tahu yang mana yang Anda modifikasi di luar simpanan.
Sven
3
Jika Anda melihat di bagian bawah posting ini DI SINI dikatakan bahwa jika Anda menjalankan git stash popdan berakhir dengan konflik, simpanan tidak dihapus ... sehingga Anda dapat lari git reset --harduntuk membatalkan pop dan kemudian mencoba solusi yang saya sarankan.
Marco Ponti
Baru saja mencoba ini dan itu tidak berfungsi setelah Anda memiliki file dalam keadaan konflik. Bahkan jika Anda memperbaiki konflik secara manual.
Sam3k
2

git stash branchakan bekerja, yang menciptakan cabang baru untuk Anda, memeriksa komit yang Anda temui ketika Anda menyimpan pekerjaan Anda, mengajukan kembali pekerjaan Anda di sana, dan kemudian menjatuhkan simpanan jika itu berhasil diterapkan. periksa ini

menghargai
sumber
2

Cara tercepat yang saya temukan adalah menyelesaikan konflik, lalu lakukan git add -u, dan kemudian lakukan git reset HEAD, itu bahkan tidak melibatkan komitmen.

Jammer
sumber
1

Menurut pertanyaan simpanan git , setelah memperbaiki konflik, git add <file>adalah tindakan yang tepat.

Setelah membaca komentar ini saya mengerti bahwa perubahan secara otomatis ditambahkan ke indeks (sesuai desain). Itu sebabnya git add <file>menyelesaikan proses resolusi konflik.

samgrigg
sumber
-1

Ini bukan cara terbaik untuk melakukannya tetapi bekerja:

$ git stash apply
$ >> resolve your conflict <<
$ >> do what you want to do with your code <<
$ git checkout HEAD -- file/path/to/your/file
Bishwas Mishra
sumber
jawaban ini tampaknya jelas salah bagi saya, karena akan membuang semua perubahan file/path/to/your/file, yang bukan apa yang diminta OP, AFAIU
oromoiluig