"Git çekme" otomatik olarak beklemedeki değişiklikleri saklayıp pop yapabilir mi?


122

Bunu nasıl çözeceğimi biliyorum:

user@host$ git pull
Updating 9386059..6e3ffde
error: Your local changes to the following files would be overwritten by merge:
    foo.bar
Please, commit your changes or stash them before you can merge.
Aborting

Ama bildirmek için bir yolu yoktur git pullyapmak stashve popbenim için dans?

Bu komutun farklı bir adı varsa sorun değil.

İçin bir kabuk takma adı oluşturmak bir git stash; git pull; git stash popçözüm, ancak daha iyi bir çözüm arıyorum.


peki ya git takma adı?
Яois

20
git stash; git pull; git stash popProgramlı olarak çalıştırmak tehlikelidir, çünkü saklanacak bir şey yoksa, işlem git stashyapılmaz, ancak git stash popson zulayı (varsa) patlar, ki bu neredeyse kesinlikle istediğiniz şey değildir . Torek kullanıcısının Stack Overflow'da bununla ilgili harika bir yayını var, ancak bulamıyorum ...
jub0bs


1
@guettli Sorunuzun bir kopya olduğunu ima etmiyordum, sadece Jubobs'un yorumunu yanıtlıyordum.
VonC

2
Bir adım daha ileri olarak, işlem ancak çekildikten sonra zula temiz bir şekilde uygulanabiliyorsa başarılı olmalıdır. Çatışma varsa, ağaç değişmeyecek şekilde tüm işlem atomik olarak başarısız olur. Yapmak istediğim şey bu: ya yerel olanlarım birleştirilmiş olarak değişiklikleri aşağı çekin ya da bir hatayla başarısız olun ve sonra ne yapacağıma manuel olarak karar vermeme izin verin. Bu tür bir git 'işlemi' mümkün mü?
Ed Avis

Yanıtlar:


185

Git 2.6+ için (28 Eylül 2015'te yayınlandı)

sadece git config ilgi çekici olan ayar:

rebase.autoStash

(Git 2.27, Q2 2020 ile artık sizde de var merge.autostash, aşağıya bakın)

Doğru olarak ayarlandığında, işlem başlamadan önce otomatik olarak geçici bir zula oluşturun ve işlem bittikten sonra uygulayın.
Bu, kirli bir çalışma ağacında yeniden kredi çalıştırabileceğiniz anlamına gelir.

Ancak dikkatli kullanın: Başarılı bir yeniden ödemeden sonraki son zula uygulaması önemsiz olmayan çatışmalara neden olabilir. Varsayılan olarak yanlıştır.

bunu şununla birleştir:

pull.rebase

Değer true olduğunda, "git pull" çalıştırıldığında varsayılan uzaktan kumandadan varsayılan dalı birleştirmek yerine, yeniden temelleme dalları getirilen dalın tepesine yerleştirilir.

git config pull.rebase true
git config rebase.autoStash true

Bu, git pullkirli bir ağaçta bile basit bir çalışma için yeterli olacaktır .
Bu durumda takma ada gerek yok.


Bkz. Commit 53c76dc (04 Temmuz 2015), Kevin Daudt ( Ikke) .
( Junio ​​C Hamanogitster tarafından birleştirildi - - in commit e69b408 , 17 Ağu 2015)

pull: rebase.autostashetkinleştirildiğinde kirli ağaca izin ver

Rebase, kirli bir iş ağacıyla karşılaştığında değişiklikleri saklamayı öğrendi, ancak git pull --rebaseyapmadı.

Yalnızca rebase.autostash, etkinleştirilmediğinde çalışma ağacının kirli olup olmadığını doğrulayın .


Not: Otomatik stash olmadan çekmek istiyorsanız ( rebase.autoStash trueayarlanmış olsa bile ), git 2.9'dan (Haziran 2016) beri:

 pull --rebase --no-autostash

Bkz 450dd1d işlemek , 1662297 taahhüt , 44a59ff işlemek , 5c82bcd işlemek , 6ddc97c işlemek , eff960b işlemek , efa195d taahhüt (2016 02 Apr) ve f66398e işlemek , c48d73b taahhüt tarafından (21 Mar 2016) Mehul Jain ( mehul2029) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 7c137bb tamamlama 2016 Nisan 13)

F66398e işlemi özellikle şunları içerir:

pull --rebase: --[no-]autostashbayrak ekle

Eğer rebase.autoStashyapılandırma değişkeni ayarlanır, "bunu geçersiz kılmak için bir yolu yoktur git pull --rebasekomut satırından".

Eğer ayarlanmışsa , mevcut değerini geçersiz kılan komut satırı bayrağını " git pull --rebase" öğretin . " " Seçeneği anladığında , bu sadece " " " " çağrıldığında seçeneği temelde yatan seçeneğe geçirmek meselesidir .--[no-]autostashrebase.autoStashgit rebase--[no-]autostashgit rebasegit pull --rebase


Uyarı: Git 2.14'ten (Q3 2017) önce, " git pull --rebase --autostash" yerel geçmiş hızlı bir şekilde yukarı akışa ilerlediğinde otomatik olarak saklanmıyordu.

Tyler Brazier ( ) tarafından commit f15e7cf'ye (01 Haziran 2017) bakın . (Göre Birleştirilmiş Junio Cı Hamano - - içinde işlemek 35898ea , 5 Haziran 2017)tylerbrazier
gitster

pull: ff --rebase --autostashkirli depoda çalışır

Ne zaman git pull --rebase --autostashkirli bir depoda bir hızlı ileri sonuçlandı, hiçbir şey autostashed ve çekme başarısız ediliyordu.
Bunun nedeni, hızlı ileri sarabildiğimizde yeniden taban çalıştırmayı önlemek için bir kısayoldu, ancak bu kod yolunda otomatik yükleme yoksayılır.


Güncelleme: Mariusz Pawelski sorar yorumlarda ilginç bir soru:

Yani herkes yeniden autostashödeme (veya pull --rebase) yaptığınız zaman hakkında yazıyor .

Ancak, birleştirmelerle normal çekme yaptığınızda kimse otomatik doldurma hakkında düşünmüyor .
Yani bunun için otomatik bir geçiş yok mu? Yoksa bir şey mi kaçırıyorum? Yapmayı tercih ederim git pull --rebaseama OP " standart " git çekme hakkında sordu

Cevap:

Orijinal iplik bu autostash özelliği tartışırken, onun için başlangıçta hem hayata geçirildi git pull(birleştirme) ve git pull --rebase.

Ama ... Junio ​​C Hamano (Git geliştiricisi) şunu kaydetti:

Eğer pull-mergetanım gereği, bu konuyu tetikleyen "sıkıntı" neden bir şey vardı, yerel değişiklik birleştirme örtüştüğünü ve bu iç birleştirme dokundu yolları dokunacaktır "pop zulası" ve büyük olasılıkla düştü" neden değil "ama daha fazla anlaşmazlığın çözülmesini bekleyin.

pull.autostashYapılandırmanın iyi bir ilave olmadığından şüpheleniyorum çünkü kötü, acı veren bir iş akışını teşvik ediyor.
Basit durumlarda zarar vermeyebilir, ancak yerel değişiklikler karmaşık olduğunda, buna sahip olmamaktan daha aktif olarak zarar verir ve yapılandırma, seçim yapma dürtüsünü ortadan kaldırır.

Denklem, "geri ödeme" için biraz farklıdır, çünkü "geri ödeme", temiz çalışan bir ağaçtan başlamanız için ısrar eder, bu nedenle "indir ve sonra durdur" sıkıntısı daha büyük hissedilir. Gevşemenin gerçek soruna daha verimli bir çözüm olabileceğinden şüpheleniyorum.

Bu nedenle, klasik bir çekme birleştirmeyle ilgili olarak aşağıdakileri yapmak daha iyidir:

kullanıcıyı " git pull" çalıştırmadan önce çalışma ağacındaki WIP'in doğası hakkında düşünmeye teşvik edin .
Başkalarının yaptıklarına müdahale edebilecek çok karmaşık bir canavar mı yoksa saklayıp geri alabileceği önemsiz bir değişiklik mi?

Eğer birincisi, " checkout -b" yapmaktan çok daha iyi olacaktır " ", yerel değişim biraz daha iyi bir şekle girene ve orijinal şubeye geçmeden önce "taahhüt" edene kadar çalışmaya devam edin.

İkincisi ise, yapması daha iyidir:

  • " git pull",
  • çelişkili bulduktan sonra koş
    • git stash,
    • git merge FETCH_HEAD ve
    • git stash pop

Bununla birlikte, Git 2.27 (Q2 2020) ile, " git pull" hiçbir pull.rebasekonfigürasyon olmadığında ve ne verilmiş ne --[no-]rebasede --ff-onlyverilmiş (bu birleştirme ile sonuçlanacak ) " " uyarmayı öğrendi .

Bkz. Commit d18c950 (10 Mart 2020), Alex Henrie ( alexhenrie) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 1c56d6f tamamlama 2020 27 Mar)

pull: kullanıcı yeniden mi yoksa birleştirmek mi gerektiğini söylemediyse uyar

İmza: Alex Henrie

Çoğunlukla acemi Git kullanıcıları " pull --rebase" demeyi unutur ve sonunda yukarı akıştan gereksiz bir birleştirme ile sonuçlanır.

Genelde istedikleri şey ya pull --rebasedaha basit durumlarda " pull --ff-only" ya da " " ana entegrasyon şubelerinin kopyasını güncellemek ve çalışmalarını ayrı ayrı yeniden düzenlemektir. Yapılandırma değişkeni daha basit durumlarda onlara yardım etmek var, ancak bunun bu kullanıcıların haberdar etmek için hiçbir mekanizma yoktur.
pull.rebase

--[no-]rebaseKomut satırından hiçbir seçenek ve pull.rebaseyapılandırma değişkeni verilmediğinde bir uyarı mesajı yayınlayın.
Bu, asla yapmak istemeyenleri pull --rebase, özel bir şey yapmak zorunda kalmayanları " " rahatsız edecektir , ancak rahatsızlığın bedeli kullanıcı başına yalnızca bir kez ödenir ve bu, bir dizi yeni kullanıcıya yardımcı olmak için makul bir maliyet olmalıdır.


Git 2.27 (Q2 2020) ile " git merge", " --autostash" seçeneğini ve yeni merge.autostashayarı öğrenir .

Bkz d9f15d3 işlemek , f8a1785 taahhüt , a03b555 işlemek , 804fe31 taahhüt , 12b6e13 taahhüt , 0dd562e işlemek , 0816f1d taahhüt , 9bb3dea işlemek , 4d4bc15 taahhüt , b309a97 taahhüt , f213f06 işlemek , 86ed00a işlemek , facca7f işlemek , be1bb60 taahhüt , efcf6cf işlemek , c20de8b işlemek , işlemek bfa50c2 , commit 3442c3d , commit 5b2f6d9 (07 Nis 2020), commit 65c425a(04 Nisan 2020) ve fd6852c'yi gerçekleştirin , 805d9ea (21 Mart 2020), Denton Liu ( Denton-L) tarafından taahhüt edilir .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde bf10200 tamamlama 2020 29 Apr)

pull: birleştirmek için --autostash

İmza: Denton Liu

Daha önce --autostashsadece birlikte çalıştı git pull --rebase.

Ancak, son yamada, öğrenilenleri birleştirin, --autostashbu nedenle artık bu kısıtlamaya sahip olmamız için hiçbir neden yok.
Rebase'de --autostasholduğu gibi birleştirmek için çekmeyi öğretin .

Ve:

rebase: apply_autostash()sequencer.c'den kullanın

İmza: Denton Liu

İn apply_autostash()işlevi, kabul ettikleri argüman türü dışında neredeyse birbirlerinin yerine geçebilecekleri builtin/rebase.ciçin apply_autostash()işleve yeterince benzerdir sequencer.c. sequencer.cExtern versiyonunu yapın ve rebase'de kullanın.

Rebase sürümü, 6defce2b02'de ("yerleşik yeniden taban : destek --autostashseçeneği", 2018-09-04, Git v2.20.0-rc0 - 8 numaralı toplu işlemde listelenen birleştirme ) C'ye dönüşümün bir parçası olarak tanıtıldı . İşlevi çoğaltmayı seçti, çünkü o zamanlar etkileşimli yeniden tabanı kabuktan C'ye dönüştüren devam eden başka bir proje vardı ve sürümünün yeniden düzenlenmesi yoluyla onlarla çatışmak istemediler . Her iki çaba da uzun süredir yapıldığından, şimdi onları özgürce birleştirebiliriz.
sequencer.capply_autostash()


2.4.2 itibariyle bu henüz uygulanmamaktadır. Belki bir gün. rebase.autoStashyalnızca yeniden taban kullanırken geçerlidir. pull.rebaseyalnızca çekme kullanılırken geçerlidir.
Randal Schwartz

"Bu, kirli bir ağaçta bile işe yarayacak basit bir git için yeterli olacaktır." Randal'ın dediği gibi, bu henüz doğru değil. Mevcut ustanın pull.c hala seçiyor die_on_unclean_work_tree.
Pradhan

1
@Pradhan Katılıyorum. Uygulama bu sabah ustalaştı ve 2.6 sürümüne geçecek. Bunu açıklığa kavuşturmak için cevabı düzenledim.
VonC

Autostash'in git ile çalıştığını doğruladım 2.5.5.
Joshua Hoblitt

1
Yani, siz rebase(veya pull --rebase) yaptığınızda herkes otomatik stash hakkında yazıyor . Ancak pull, birleştirmelerle normal yaptığınızda kimse otomatik olarak saklamayı düşünmüyor . Yani bunun için otomatik bir geçiş yok mu? Yoksa bir şey mi kaçırıyorum? git pull --rebasegit pull
Yapmayı

41

Yaklaşan kaşifler için birkaç saniye kazanmak için işte bir özet (@VonC sayesinde):

git pull --rebase --autostash

6
Mesele şu: a git config pull.rebase trueve sonrasında git config rebase.autoStash trueihtiyacınız olan tek şey git pull. Sadece git pull. Başka seçenek gerekmez.
VonC

3
--autostashSeçenek için en az Git 2.9'a ihtiyacınız olduğu görülüyor . -c rebase.autoStash=trueİleriye Git 2.6 çalışır.
ntc2

15

Yukarıdaki açıklamada belirtildiği gibi, iki yapılandırma değerini ayarlamak şu anda çalışmamaktadır git pull, çünkü otomatik depolama yapılandırması yalnızca gerçek yeniden yüklemeler için geçerlidir. Bu git komutları istediğinizi yapar:

git fetch
git rebase --autostash FETCH_HEAD

Veya takma ad olarak ayarlayın:

git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'

O zaman yap:

git pullr

Elbette bu takma ad istenildiği gibi yeniden adlandırılabilir.


7

Git 2.6+ ile şunları kullanabilirsiniz:

alias gup='git -c rebase.autoStash=true pull --rebase'

Bu --rebase, git-pull'ın rebaseyerine kullanılmasını sağlar merge, böylece gibi ayarlar / seçenekler --ff-onlyuygulanmaz.

--ff-onlyVarsayılan olarak ( git pull --ff-only) ile çekmek için bir takma ad kullanıyorum ve guphızlı ileri birleştirme mümkün değilse veya saklanan değişiklikler varsa (yukarıdan) kullanabilirim .


Arasındaki temel fark nedir git pull --ff-onlyvegit pull pull --rebase --autostash
alper

0

Daha önce de belirttiğiniz gibi, bunu yapmanın yolu budur. Yazarken kaydetmek ve kısayolu kullanmak için takma ad olarak kullanabilir veya tek bir satırda kullanabilirsiniz (bir takma ad da olabilir)

git stash && git pull --rebase && git stash pop

Sizin yaptığınızla aynı şeyi yapacak, ancak tek bir satırda (&&) ve takma ad olarak ayarlanmışsanız, daha da kısa olacaktır.

Aşağıdaki satırlar, siz çekmeden / itmeden önce gelen / giden değişiklikleri gösterecektir.

git log ^master origin/master
git log master ^origin/master

8
Bu yaklaşım güvensizdir: Eğer stash popsaklanacak bir şey yoksa, ilk komut hiçbir şey yapmaz ve daha sonra önceden rastgele bazı şeyleri çözer.
John Zwinck

Daha açık olmak gerekirse: git stashherhangi bir şey saklamasa bile hata kodu "döndürmez", böylece && yine de devam edecek git pullve git stash popönceki bir zulayı açacaktır . Bir şeyi saklayacağından çok emin olmadığınız sürece bunu kullanmayın!
MoonLite
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.