Git stash çakışmasını kesin olarak nasıl çözebilirim?


495

Bu soruda da sorulduğu gibi , git stash popbir taahhüde tüm değişiklikleri eklemeden çakışmayı nasıl çözeceğimizi bilmek istiyorum (tıpkı bir çatışma olmadan "git stash pop" gibi).

Mevcut yaklaşımım çok soğuk çünkü bunu şu şekilde yapıyorum:

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

[Güncelleme] Yeniden üretmek için bir yol:

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: Scy'nin çözümü gibi geçici çözümlerin yalnızca boş HEAD'ler için çalıştığını, ancak HEAD'in aynı içeriğe sahip olmadığı ilk sorunu çözmediğini göstermek için örneğe 'üçüncü' adlı yeni bir dosya eklendi bir yönelik git stash popbir çatışma olmadan.


Böylece git add, çözümlenmiş çakışma dosyalarınızı etkili bir şekilde dizine yerleştiriyorsunuz ve dizinimizde yer almasını istemiyor musunuz?
Romain

Evet bu doğru. Ben sadece git stash pophiçbir çakışma meydana geldiğinde (ama hangi dosyaları birleştirilmesi gerektiğini bildirimi ile) olan davranışı istiyorum .
Sven

2
Bunun cevabı burada gibi görünüyor: stackoverflow.com/questions/3945826/git-stash-questions . Seçilen cevapta 4. yorumda Adam git'in neden bunu yaptığını açıklıyor.
Patrick

@Patrick Bu bilgi için teşekkür ederiz - bu yüzden "tasarım" ile hiçbir çözüm olmayacak gibi görünüyor
Sven

Yanıtlar:


509

Başka cevapları takip etme

Onları takip edebilirsiniz :). Ancak, bir taahhütte bulunmanın ve daha sonra bu taahhüdü kaldırmak için şubeyi sıfırlamanın ve diğer cevaplarda önerilen benzer geçici çözümlerin bu sorunu çözmenin temiz yolu olduğunu düşünmüyorum.

Temiz çözüm

Aşağıdaki çözüm benim için çok daha temiz görünüyor ve Git'in kendisi tarafından da öneriliyor - git statusdepoda bir çakışma ile yürütmeyi deneyin :

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

Öyleyse Git'in önerilerini yapalım (işe yaramaz taahhüt yapmadan):

  1. El ile (veya birleştirme aracını kullanarak aşağıya bakın) çakışmaları çözer.
  2. Kullanım git resetçözüldü ve unstage değişiklikler gibi işaretleyiniz çatışma (lar). Herhangi bir parametre olmadan çalıştırabilirsiniz ve Git her şeyi dizinden kaldırır. Daha git addönce idam etmek zorunda değilsin .
  3. Son olarak, zulayı kaldırın git stash drop, çünkü Git bunu çakışmada yapmaz.

Komut satırına çevrildi:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

Varsayılan davranışın açıklaması

Çatışmaları çözülmüş olarak işaretlemenin iki yolu vardır: git addve git reset. İken git resetendeks, gelen giderilmiş ve kaldırır dosyaları gibi işaretler çatışmaları git addda çözülmüş olarak işaretleri çatışmaları, ama endekste dosyaları tutar.

Bir çakışma çözüldükten sonra dizine dosya eklemek amaçlanmıştır. Bu şekilde, değişiklikleri önceki saklamadan ve çakışma çözüldükten sonra yaptığınız değişiklikleri ayırt edebilirsiniz. Beğenmediyseniz, her git resetşeyi dizinden kaldırmak için her zaman kullanabilirsiniz .

Birleştirme araçları

KDiff3 , Meld vb. Gibi çatışmaları çözmek için 3 yollu birleştirme araçlarından herhangi birini manuel olarak yapmak yerine kullanmanızı şiddetle tavsiye ederim . Genellikle çatışmaların tamamını veya çoğunluğunu kendiliğinden çözer. Çok büyük bir zaman tasarrufu!


32
@kamalpal git stash popçatışmalar başarısız olduğunda gerekli gibi görünüyor .
Emile Bergeron

21
@kamalpal evet, Git size bir çakışma durumunda saklamanın düşürülmediğini bile bildirir. Ve soru böyle bir durumla ilgiliydi, bu yüzden o saklamayı korumak istemiyorsanız gerçekten yürütmeniz gerekiyorgit stash drop .
David Ferenczy Rogožan

@ DavidFerenczyRogožan Git stash girişini düşürmediğini bana hiç bildirmedi. Sürüm 2.17.1 burada.
Robert Siemer

298

Kökeni çekmek için değişikliklerinizi sakladığınız bu senaryoya sahip olduğunuzu varsayalım. Muhtemelen yerel değişiklikleriniz sadece debug: truebazı ayarlar dosyasında olduğu için. Şimdi çekiyorsunuz ve birisi yeni bir ortam yarattı ve bir çatışma yarattı.

git status diyor:

# 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")

Tamam. Git'in önerdiği şeye gitmeye karar verdim: Çatışmayı çözdüm ve taahhüt ettim:

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

Şimdi çalışma kopyam istediğim durumda, ama sahip olmak istemediğim bir taahhüt oluşturdum. Çalışma kopyamı değiştirmeden bu taahhütten nasıl kurtulurum? Bekle, bunun için popüler bir komut var!

git reset HEAD^

Çalışan kopyam değişmedi, ancak Devam Eden Çalışma taahhüdü gitti. Tam olarak istediğim buydu! ( --softBurada kullanmamaya dikkat edin , çünkü zulanızda otomatik olarak birleştirilmiş dosyalar varsa, bunlar otomatik olarak sahnelenir ve böylece bu dosyaların daha sonra yeniden hazırlanmasına neden olursunuz reset.)

Ancak bir şey daha kaldı: Man sayfası git stash popbize, "devleti uygulamak çatışmalarla başarısız olabilir; bu durumda, stash listesinden kaldırılamaz. Çakışmaları elle çözmeniz ve git stash dropdaha sonra manuel olarak aramanız gerekir." Şimdi tam olarak bunu yapıyoruz:

git stash drop

Ve bitti.


34
Sadece çalışma ağacını etkilemesi gereken bir şey için kasıtlı olarak HEAD ^ ... sıfırlama yapmak zorunda kalmanın sadece çirkinliği var.

6
Neden sadece çatışmaları çözüp git add <resolved conflict files>takip etmiyoruz git reset HEAD?
BoltzmannBrain

Öneri için teşekkür ederiz, ancak bu, ilk sorunu, git stash popçatışmasız gibi aynı davranışta bulunmadığı için düzeltmez . Çakışmayı yapmadan önce HEAD'e başka bir dosya eklemeniz yeterlidir git stash popve bundan git commit -a -m WIPsonra yeni dosyayı taahhüde ekleyebilirsiniz. Ancak bir çakışma olmadan, sadece yeni dosya HEAD'de kalır, ancak git stash popdosyalar değil .
Sven

7
Önce taahhüt sonra geri almanın gerekli olduğunu düşünmüyorum. Basitçe Dawid Ferenczy cevap sıfırlamak aynı şeyi yapacak
vladkras

3
Windows kullanıcıları için, ^özel bir hat devamı olarak kullanılır ve sizi bir Daha? komut yerine komut istemi. Bunun yerine kullanın: git reset --soft HEAD~1. Bkz nasıl-i-silme-unpushed-git-kaydedilmesini?
mrfelis

87

Çakışmayı gidermek için yaptığınız değişiklikleri eklemek yerine, değişikliklerinizi git reset HEAD filehazırlamadan çakışmayı çözmek için kullanabilirsiniz .

Ancak bu komutu iki kez çalıştırmanız gerekebilir. Bir kez çatışmayı çözülmüş olarak işaretlemek için ve bir kez de çatışmayı çözme rutini tarafından yapılan değişiklikleri bozmak.

Şu anda bir tane olmasa da, her ikisini de aynı anda yapan bir sıfırlama modunun olması mümkündür.


2
Sıfırlama modu aradığım moddur - diğer geçici çözümler açıkladığım gibi ve 5'ten fazla dosya için pratik değildir.
Sven

25
Ve daha sonra "git stash pop" u bitirmek için "git stash drop" kullanın.
David Liu

2
Her ne kadar soru bunu açıkça sormasa da, bir çakışma durumunda stash otomatik olarak bırakılmadığından cevabı "git stash drop" içerecek şekilde güncellemek yararlı olabilir.
Abhishek Pathak

29
git checkout stash -- .

benim için çalıştı.

Not : Bu, stash'daki değişiklikleri çalışma kopyanızla birleştirmeye çalışmadığı için tehlikeli olabilir, ancak bunun yerine stashed dosyalarla üzerine yazar . Böylece taahhüt edilmeyen değişikliklerinizi kaybedebilirsiniz.


Bu, "git pull --autostash" istenmeyen birleştirme işlemlerini ve git checkout stash'ı tanıttığında yardımcı oldu. koşulsuz olarak stash'daki çatışmaların üzerine yazıyor
Alec Istomin

11
git add .
git reset

git add . TÜM dosyaları aşamayı gidip çakışmayı çözdüğünü söyleyecek

git reset bir taahhüt oluşturmadan TÜM aşamalı dosyaları bozar


Bu aslında kötü bir cevap değil, o git add -uzamana çok benziyorgit reset
ebob

4

Görünüşe göre aradığınız cevap bu olabilir, bunu henüz kişisel olarak denemedim, ancak hile yapabileceği anlaşılıyor. Bu komutla GIT, değişiklikleri taahhüt için eklemeye çalışmadan, değişiklikleri eskisi gibi uygulamaya çalışacaktır.

git stash apply --index

İşte tam açıklama:

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


Bu ipucu için teşekkürler, ama bu zaten yaptığımda yardımcı olmaz git stash pop- ya da bunu geri almanın ve bir çatışmaya gireceğini git stash apply --indexöğrendiğimde yapmanın bir yolu var git stash popmı?
Sven

Bunu nasıl oluşturacağınıza dair bir örnek ekledim - 10'dan fazla dosyayı düzenlediğinizi hayal edin, böylece hangilerinin stash dışında değiştirdiğinizi bilmiyorsunuz.
Sven

3
Eğer bu yazının altındaki bakacak olursak BURAYA o koşarsan söylüyor git stash popve çatışmaları ile biter Çalıştırmak böylece zulası ... kaldırılmış almaz git reset --hardben önerilen çözümü deneyin ardından pop geri almak ve.
Marco Ponti

Sadece bunu denedim ve çatışma durumunda bir dosyaya sahip olduktan sonra çalışmıyor. Çatışmayı manuel olarak düzeltseniz bile.
Sam3k

2

git stash branchsizin için yeni bir şube yaratan işler, işinizi saklarken bulunduğunuz taahhüdü kontrol eder, çalışmanızı orada yeniden uygular ve ardından başarılı bir şekilde uygularsa saklamayı bırakır. bunu kontrol et



1

Git zulası sorulara göre , çatışmayı düzelttikten sonra git add <file>, doğru eylem yoludur.

Bu yorumu okuduktan sonra değişikliklerin otomatik olarak dizine (tasarım gereği) eklendiğini anladım. Bu yüzden git add <file>çatışma çözme sürecini tamamlar.


-1

Bunu yapmanın en iyi yolu değil ama işe yarıyor:

$ git stash apply
$ >> resolve your conflict <<
$ >> do what you want to do with your code <<
$ git checkout HEAD -- file/path/to/your/file

bu cevap benim için basit bir yanlış gibi görünüyor, çünkü tüm değişiklikleri file/path/to/your/fileatmış olacak, bu OP istedi ne değil, AFAIU
oromoiluig
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.