git stash -> gabungkan perubahan simpanan dengan perubahan saat ini

187

Saya membuat beberapa perubahan pada cabang saya dan menyadari bahwa saya lupa saya telah menyembunyikan beberapa perubahan lain yang diperlukan untuk cabang tersebut. Apa yang saya inginkan adalah cara untuk menggabungkan perubahan simpanan saya dengan perubahan saat ini.

Apakah ada cara untuk melakukan ini?

Yang lebih untuk kenyamanan, saya akhirnya menyerah dan melakukan perubahan pertama saya saat ini, kemudian perubahan saya simpanan, tapi saya lebih suka untuk mendapatkannya dengan satu gerakan.

Bemis
sumber
Mungkin duplikat dari stackoverflow.com/q/1360712/72178
ks1322
Jawaban joshua harus menjadi jawaban yang diterima. Posting stackoverflow ini adalah tautan google pertama untuk pertanyaan ini, berikan jawaban yang benar ke internet!
Jérôme

Jawaban:

272

Saya baru saja menemukan bahwa jika perubahan yang tidak dikomit ditambahkan ke indeks (yaitu "dipentaskan", menggunakan git add ...), maka git stash apply(dan, mungkin, git stash pop) benar-benar akan melakukan penggabungan yang tepat. Jika tidak ada konflik, Anda adalah emas. Jika tidak, selesaikan seperti biasagit mergetool , atau secara manual dengan editor.

Untuk lebih jelasnya, ini adalah proses yang saya bicarakan:

mkdir test-repo && cd test-repo && git init
echo test > test.txt
git add test.txt && git commit -m "Initial version"

# here's the interesting part:

# make a local change and stash it:
echo test2 > test.txt
git stash

# make a different local change:
echo test3 > test.txt

# try to apply the previous changes:
git stash apply
# git complains "Cannot apply to a dirty working tree, please stage your changes"

# add "test3" changes to the index, then re-try the stash:
git add test.txt
git stash apply
# git says: "Auto-merging test.txt"
# git says: "CONFLICT (content): Merge conflict in test.txt"

... yang mungkin Anda cari.


tl; dr

Jalankan git adddulu.

Joshua Warner
sumber
8
Peretasan seperti itu, tapi hei, itu berfungsi dan tampaknya menjadi satu-satunya cara untuk melakukan ini. Saya berharap ada git stash apply --forceatau sesuatu.
Matt Kantor
13
Sebenarnya, ini bukan peretasan - ini adalah peningkatan dari apa yang Anda inginkan, karena Anda dapat dengan mudah kembali ke perubahan dalam indeks.
hoffmanc
2
Wow, apakah perilaku ini benar-benar dimaksudkan oleh git?
edi9999
9
Saya tidak berpikir ada sesuatu yang pernah "dimaksudkan" oleh git. Firasat saya adalah sekarang bahwa git melakukannya secara kebetulan.
Profpatsch
5
Ini solusi sempurna. Saya baru saja melakukannya git add .,, git stash applylalu git resetmenerapkan simpanan ke perubahan pekerjaan saya dan bergabung tanpa harus membuat komitmen.
Stephen Smith
70

Menjalankan git stash popatau git stash applypada dasarnya merupakan gabungan. Anda seharusnya tidak perlu melakukan perubahan saat ini kecuali file yang diubah di simpanan juga diubah dalam copy pekerjaan, dalam hal ini Anda akan melihat pesan kesalahan ini:

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Dalam hal ini, Anda tidak dapat menerapkan simpanan ke perubahan saat ini dalam satu langkah. Anda dapat mengkomit perubahan, menerapkan simpanan, mengkomit kembali, dan menghancurkan dua komit menggunakan git rebasejika Anda benar-benar tidak ingin dua komit, tetapi itu mungkin lebih banyak masalah yang layak.

Brandan
sumber
1
Saya memang mendapatkan pesan itu - perubahan tidak bertentangan tetapi berbagi file yang sama, sekitar menggunakan simpanan / mendaftar?
Bemis
1
Maaf, itulah yang saya maksud dengan "menggabungkan konflik", tapi itu pilihan kata yang buruk. Saya pikir pesan kesalahan itu cukup final: jika file yang diubah dalam copy pekerjaan juga diubah di simpanan, Anda tidak bisa menerapkan simpanan. Saya telah memperbarui jawaban saya dengan solusi yang memungkinkan.
Brandan
3
Saya tidak akan menganggap ini sebagai jawaban dalam semua kasus. Anda mungkin telah menyembunyikan hanya sebagian dari set perubahan dalam file tertentu karena Anda ingin menguji sesuatu saat mengembangkan. Dan Anda mungkin tidak ingin mengkomit konten file saat ini pada saat ini (atau tidak sama sekali) karena WIP. Ini adalah masalah nyata dengan git yang menyembunyikan perubahan tidak dapat digabungkan ke cabang Anda saat ini
Thomas Watson
21
Jawaban Joshua Warner haruslah yang ditandai sebagai benar. Untuk menggabungkan simpanan, atur perubahan Anda, terapkan simpanan, atasi konflik apa pun, dan kemudian (jika diinginkan) hapus tahapan perubahan Anda.
Vroo
4
"Anda dapat melakukan perubahan, menerapkan simpanan, melakukan lagi, dan menghancurkan dua komit menggunakan git rebase jika Anda benar-benar tidak ingin dua komit, tetapi itu mungkin lebih banyak masalah yang layak dilakukan." Alih-alih ini yang bisa Anda lakukan: Lakukan perubahan, terapkan simpanan, lalu git commit --amend.
gabe
27

Apa yang saya inginkan adalah cara untuk menggabungkan perubahan simpanan saya dengan perubahan saat ini

Berikut ini opsi lain untuk melakukannya:

git stash show -p|git apply
git stash drop

git stash show -pakan menampilkan patch simpanan yang terakhir disimpan. git applyakan menerapkannya. Setelah penggabungan selesai, simpanan gabungan dapat dijatuhkan dengan git stash drop.

ks1322
sumber
1
Terima kasih untuk ini - Saya tidak tahu mengapa git stash poptidak hanya melakukan ini dalam kasus di mana penggabungan berlaku bersih ...
Iguananaut
Versi lanjutan: git stash show -p --no-color | git apply --3way( --3way= mundur pada penggabungan 3-arah jika tambalan gagal).
DmitrySandalov
Tetapi git stash show -pmenciptakan perbedaan antara konten simpanan dan komit kembali ketika entri simpanan pertama kali dibuat . Jadi ini akan menimpa perubahan file OP yang dibuat.
Paul F. Wood
Kenapa ditimpa? Perbedaan yang dihasilkan dengan git stash show -pakan digabungkan oleh git apply, jika memungkinkan untuk dilakukan tanpa konflik.
ks1322
1

Cara saya melakukan ini adalah dengan git addini dulu git stash apply <stash code>. Ini cara paling sederhana.

pengguna3856437
sumber
4
Bagaimana ini bukan salinan persis dari jawaban yang diterima?
RomainValeri
0

Seperti yang disarankan oleh @Brandan, inilah yang perlu saya lakukan untuk berkeliling

error: Your local changes to the following files would be overwritten by merge:
       file.txt
Please, commit your changes or stash them before you can merge.
Aborting

Ikuti proses ini:

git status  # local changes to `file`
git stash list  # further changes to `file` we want to merge
git commit -m "WIP" file
git stash pop
git commit -m "WIP2" file
git rebase -i HEAD^^  # I always use interactive rebase -- I'm sure you could do this in a single command with the simplicity of this process -- basically squash HEAD into HEAD^
# mark the second commit to squash into the first using your EDITOR
git reset HEAD^

Dan Anda akan dibiarkan dengan perubahan lokal yang sepenuhnya digabungkan ke file, siap untuk melakukan pekerjaan / pembersihan lebih lanjut atau membuat satu komitmen yang baik. Atau, jika Anda tahu konten gabungan fileakan benar, Anda bisa menulis pesan yang pas dan melompat git reset HEAD^.

knickum
sumber
0

Mungkin, itu bukan ide terburuk untuk digabungkan (via difftool) dari ... ya ... cabang!

> current_branch=$(git status | head -n1 | cut -d' ' -f3)
> stash_branch="$current_branch-stash-$(date +%yy%mm%dd-%Hh%M)"
> git stash branch $stash_branch
> git checkout $current_branch
> git difftool $stash_branch
Frank-Rene Schäfer
sumber
0

kamu bisa dengan mudah

  1. Komit perubahan Anda saat ini
  2. Lepaskan simpanan Anda dan selesaikan konflik
  3. Mengkomit perubahan dari simpanan
  4. Atur ulang lunak untuk komit asal Anda (komit terakhir benar)
Finelf
sumber
-1

Opsi lain adalah melakukan "git simpanan" lain dari perubahan yang tidak dikomit lokal, lalu menggabungkan dua simpanan git. Sayangnya git tampaknya tidak memiliki cara untuk dengan mudah menggabungkan dua simpanan. Jadi salah satu pilihan adalah membuat dua file .diff dan menerapkan keduanya - jangan sampai itu bukan komitmen ekstra dan tidak melibatkan proses sepuluh langkah: |

caranya: https://stackoverflow.com/a/9658688/32453

rogerdpack
sumber
Ternyata masalah menerapkan satu diff menjadi masalah menerapkan dua diff. Selain itu, solusi yang diterima tidak melibatkan komit, hanya tahap, dan itu hanya satu perintah (git add). (Saya bukan peniru.)
Eike
Bagi saya setidaknya rasanya lebih sederhana, sedikit sihir voodoo ... tepuk tangan
rogerdpack