git stash -> mevcut değişikliklerle depolanan değişikliği birleştir


187

Şubemde bazı değişiklikler yaptım ve söz konusu şubede gerekli diğer değişiklikleri sakladığımı unuttuğumu fark ettim. İstediğim şey, saklanan değişikliklerimi mevcut değişikliklerle birleştirmenin bir yoludur.

Bunu yapmanın bir yolu var mı?

Daha fazla kolaylık için, sonunda vazgeçtim ve önce mevcut değişikliklerimi, sonra da saklanmış değişikliklerimi taahhüt ettim, ama onları tek bir hamle ile almayı tercih ederdim.



joshua'nın cevabı kabul edilen cevap olmalıdır. Bu stackoverflow yayın, bu soru için ilk google bağlantısıdır, internete doğru cevabı verin!
Jérôme

Yanıtlar:


272

Sadece taahhüt edilmemiş değişikliklerin dizine eklenirse (yani "aşamalı", kullanarak git add ...), o zaman git stash apply(ve muhtemelen git stash pop) aslında uygun bir birleştirme yapacağını keşfettim . Çatışma yoksa, sen altınsın. Değilse, bunları her zamanki gibi git mergetoolveya bir düzenleyiciyle manuel olarak çözün .

Açık olmak gerekirse, bahsettiğim süreç bu:

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"

... muhtemelen aradığınız şey budur.


tl; Dr.

git addÖnce koş .


8
Böyle bir hack, ama hey, işe yarıyor ve bunu yapmanın tek yolu gibi görünüyor. Keşke falan olsaydı git stash apply --force.
Matt Kantor

13
Aslında, bu bir hack değil - dizindeki değişikliklere kolayca geri dönebileceğiniz için, ne istediğinize göre bir gelişme.
hoffmanc

2
Vay canına, bu davranış gerçekten git?
edi9999

9
Git'in şimdiye kadar “tasarladığı” bir şey olduğunu sanmıyorum. Benim önsezim şimdi git bir şey şans eseri yapar.
Mart'ta Profpatsch

5
Bu mükemmel bir çözüm. Sadece yaptım git add ., git stash applydaha sonra, git resethareketin kaydedilmesini yapmak zorunda kalmadan benim çalışma değişiklikleri ve birleştirme için zulası uygulamak.
Stephen Smith

70

Koşmak git stash popya git stash applyda aslında bir birleşme. Stash'da değiştirilen dosyalar da çalışma kopyasında değiştirilmedikçe geçerli değişikliklerinizi yapmanız gerekmezdi, bu durumda bu hata mesajını görürsünüz:

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

Bu durumda, stash'ı mevcut değişikliklerinize tek bir adımda uygulayamazsınız. Değişiklikleri taahhüt edebilir, zulayı uygulayabilir, tekrar taahhüt git rebaseedebilir ve gerçekten iki taahhüt istemiyorsanız kullanarak bu iki taahhüdü ezebilirsiniz, ancak bu değerinde daha fazla sorun olabilir.


1
Bu mesajı aldım - değişiklikler çakışmıyor, ancak aynı dosyaları paylaşıyor, herhangi bir yerde stashes / Apply's kullanıyor musunuz?
Bemis

1
Maalesef, "birleşme çatışmaları" ile kastettiğim budur, ancak bu kötü bir kelime seçimiydi. Hata mesajının oldukça son olduğunu düşünüyorum: çalışma kopyasında değiştirilen dosyalar da stash içinde değiştirilirse, stash'ı uygulayamazsınız. Cevabımı olası bir çözümle güncelledim.
Brandan

3
Bunu her durumda bir cevap olarak görmezdim. Belirli bir dosyadaki bir dizi değişikliğin yalnızca bir kısmını saklamış olabilirsiniz çünkü geliştirme sırasında bir şeyi test etmek istersiniz. Ve dosyanın geçerli içeriğini WIP olduğu için bu noktada (veya hiç) taahhüt etmek istemeyebilirsiniz. Depshed değişikliklerinin mevcut şubenize birleştirilememesi git ile ilgili gerçek bir sorundur
Thomas Watson

21
Joshua Warner'ın cevabı doğru olarak işaretlenmiş olmalı. Bir zulayı birleştirmek için değişikliklerinizi yapın, zulayı uygulayın, çatışmaları ele alın ve ardından (istenirse) değişikliklerinizi bozun.
Vroo

4
"Gerçekten iki taahhüt istemiyorsanız, değişiklikleri tekrarlayabilir, zulayı uygulayabilir, tekrar taahhüt edebilir ve git rebase'i kullanarak bu iki taahhüdü ezebilirsiniz, ancak bu değerinde daha fazla sorun olabilir." Bunun yerine şunları yapabilirsiniz: Değişiklikleri uygulayın, zulayı uygulayın ve sonra git commit --amend.
gabe

27

İstediğim şey, saklanan değişikliklerimi mevcut değişikliklerle birleştirmenin bir yolu

İşte bunu yapmak için başka bir seçenek:

git stash show -p|git apply
git stash drop

git stash show -pson kaydedilen saklamanın yamasını gösterecektir. git applyuygulayacak. Birleştirme tamamlandıktan sonra, birleştirilmiş saklamak ile bırakılabilir git stash drop.


1
Bunun için teşekkürler - git stash popBirleştirme temiz bir şekilde uygulandığında neden sadece bunu yapmıyor bilmiyorum ...
Iguananaut

Genişletilmiş sürüm: git stash show -p --no-color | git apply --3way( --3way= düzeltme eki başarısız olursa 3 yönlü birleştirme işlemine geri döner).
DmitrySandalov

Ancak , saklanan içerik ile saklanan giriş ilk oluşturulduğunda geri gönderme arasındagit stash show -p bir fark oluşturur . Bu OP'nin yaptığı çalışma dosyası değişikliklerinin üzerine yazacaktır.
Paul F. Wood

Neden üzerine yazılmalı? İle üretilen fark , çatışmalar olmadan git stash show -pyapılabiliyorsa birleştirilecektir git apply.
ks1322

1

Bunu git addilk önce bu şekilde yapıyorum git stash apply <stash code>. Bu en basit yol.


4
Bu tl; dr'nin kabul edilen cevabının tam bir kopyası değil mi?
RomainValeri

0

@Brandan tarafından önerildiği gibi, etrafta dolaşmak için yapmam gereken şey

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

Bu işlemi takip edin:

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^

Ve daha fazla çalışma / temizlik yapmaya veya tek bir iyi taahhütte bulunmaya hazır, tamamen birleştirilmiş yerel değişikliklerle bırakılacaksınız file. Veya, birleştirilen içeriğinin filedoğru olacağını biliyorsanız, uygun bir mesaj yazıp atlayabilirsiniz git reset HEAD^.


0

Belki de (difftool aracılığıyla) ... bir daldan birleşmek en kötü fikir değildir!

> 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

0

kolayca yapabilirsin

  1. Mevcut değişikliklerinizi yapın
  2. Zulanızı kaldırın ve çakışmaları çözün
  3. Stash'tan değişiklik yapma
  4. Geldiğin taahhüt için yumuşak sıfırlama (son doğru taahhüt)

-1

Diğer bir seçenek, yerel taahhüt edilmemiş değişikliklerin başka bir "git stash" ı yapmak ve ardından iki git stash'ını birleştirmektir. Ne yazık ki git'in iki zulayı kolayca birleştirmenin bir yolu yok gibi görünüyor. Bu yüzden bir seçenek, iki .diff dosyası oluşturmak ve her ikisini de uygulamaktır - ancak ekstra bir taahhüt değil ve on adım süreci içermez: |

nasıl yapılır: https://stackoverflow.com/a/9658688/32453


Bir fark uygulama problemini iki fark uygulama problemine dönüştürür. Ek olarak, kabul edilen çözüm bir taahhüt içermez, sadece bir aşama içerir ve sadece tek bir komuttur (git add). (Ben downvoter değilim.)
Eike

Benim için en azından daha basit, daha az vudu büyüsü hissettiriyor ... şerefe!
rogerdpack
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.