“Git reset” ve “git checkout” arasındaki fark nedir?


440

Hep düşündüm git resetve git checkouther ikisi de bir spesifik işlemeye proje geri getirmek anlamında, aynı şekilde. Ancak, gereksiz oldukları için tam olarak aynı olamayacaklarını hissediyorum. İkisi arasındaki gerçek fark nedir? Svn sadece svn cotaahhüt geri dönmek zorunda olduğu gibi, biraz kafam karıştı .

KATMA

VonC ve Charles arasındaki farkları açıkladı git resetve git checkoutgerçekten iyi. Şimdiki anlayışım, git resettüm değişiklikleri belirli bir taahhüde geri döndürürken, git checkoutaz çok bir şubeye hazırlanıyor. Aşağıdaki iki şemayı bu anlayışa gelmede oldukça yararlı buldum:

http://a.imageshack.us/img651/1559/86421927.png http://a.imageshack.us/img801/1986/resetr.png

EKLENDİ 3

Http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html adresinden ödeme ve sıfırlama öykünebilir rebase.

resim açıklamasını buraya girin

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

resim açıklamasını buraya girin



Re: "Yanlış mı yoksa aşırı basitleştirilmiş mi?" Evet, bu ilk diyagram, ödeme ve sıfırlama arasındaki fark konusunda yanıltıcıdır. ( -- filesVaryantlarla ilgili sorun olmayabilir ; emin değilim.) Bu şema, ana farkı, indeksi mi yoksa WD'yi mi etkilediğidir. Bununla ilgili cevabımı gör. 2. ve 3. diyagramlar gerçek farkı görmek için çok faydalıdır. 4. ve 5. diyagramlar, bu komutların ne yaptığını anladığınızı kontrol etmek için yararlıdır, ancak oraya ulaşmanıza gerçekten yardımcı olmaz.
LarsH

En faydalı özeti vermek için "Git Tools Reset Demystified" bölümünün "Check it out" bölümünü buldum .
Josiah Yoder

1
prosseek: @LarsH ile ilk diyagramın yanıltıcı olduğunu kabul ediyorsanız, kaldırabilir misiniz lütfen?
Josiah Yoder

Ödeme ve sıfırlamanın, rebase'in yalnızca 2. bölümünü taklit ettiğini ve think-like-a-git.netveri kaybını önlemek için ek adımlar (bağlantılı makalede sağlanan ) gerektiğini lütfen unutmayın .
cowlinator

Yanıtlar:


198
  • git resetözellikle dizini güncellemek, HEAD'i hareket ettirmekle ilgilidir.
  • git checkouthakkındadır çalışma ağacını güncellenmesi (endeks veya belirtilen ağaca). HEAD'ı yalnızca bir şubeyi teslim aldığınızda güncelleyecektir (eğer değilse, ayrılmış bir HEAD ile sonuçlanırsınız ).
    (aslında, Git 2.23 3. Çeyrek 2019 ile bu git restoregerekli olmayabilir git checkout)

Karşılaştırıldığında, svn'nin bir dizini olmadığından, yalnızca çalışan bir ağaç, svn checkoutverilen bir düzeltmeyi ayrı bir dizine kopyalar.
İçin daha yakın eşdeğer git checkout:

  • svn update (aynı şubedeyseniz, aynı SVN URL'sini kastediyorsanız)
  • svn switch (örneğin aynı şubeyi, ancak başka bir SVN repo URL'sinden ödeme yaparsanız)

Tüm bu üç çalışma ağacı değişikliği ( svn checkout,update , switch) Git tek komut vardır: git checkout.
Ancak git de indeks kavramına sahip olduğundan (repo ile çalışma ağacı arasındaki “evreleme alanı”), ayrıca var git reset.


Thinkeye yorumlarda " Demystified Reset " başlıklı makaleden bahsediyor .

Örneğin, iki şubemiz varsa, 'master ' ve ' develop' farklı taahhütlere işaret ediyor ve şu anda ' develop' (yani HEAD bunu gösteriyor) ve koşuyoruz git reset master, ' develop' şimdi aynı taahhüde işaret edecek ' master'yapar.

Öte yandan, bunun yerine git checkout master , ' develop' hareket HEADetmeyecek , kendisi hareket edecektir. HEADşimdi işaret edecek ' master'.

Yani, her iki durumda HEADda taahhütte bulunmak için harekete geçiyoruz A, ancak bunu nasıl yaptığımız çok farklı. resetşubeyi hareket ettirecekHEAD noktalarını HEADbaşka bir noktaya kasayı taşır .

http://git-scm.com/images/reset/reset-checkout.png

Yine de bu noktalarda:

Larsh ekler yorumlarda :

Bu cevabın ilk paragrafı yanıltıcıdır: " git checkout... sadece bir şubeyi kontrol ederseniz HEAD'i güncelleyecektir (eğer değilse, kopuk bir HEAD ile sonuçlanırsınız)".
Doğru değil: git checkoutşube olmayan bir taahhütte bulunsanız bile HEAD'i güncelleyecektir (ve evet, kopuk bir HEAD ile sonuçlanırsınız, ancak yine de güncellenmiştir).

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novo aynı fikirde yorumlarda :

@LarsH doğru.
İkinci mermi, HEAD'ın ne olduğu konusunda yanlış bir anlayışa sahipse, HEAD'ı sadece bir şubeyi kontrol ettiğinizde güncelleyecektir.
HEAD nerede olursanız olun gölge gibi gider.
Bazı şube dışı referansları (örneğin, bir etiketi) veya doğrudan bir taahhüdü kontrol etmek KAFA hareket edecektir. Ayrılmış kafa, KAFA'dan ayrıldığınız anlamına gelmez, bu da başın görebileceğiniz bir dal ref'den ayrıldığı anlamına gelir, örn git log --pretty=format:"%d" -1.

  • Bağlı kafa durumları (HEAD -> ,
  • müstakil hala görünecek (HEAD, ancak bir dal ref için bir ok olmayacaktır.

7
git resetŞube "etiket" değiştirmek ve isteğe bağlı olarak dizin veya çalışma ağacı bir yan etkisi olarak güncelleme hakkında olduğunu söyleyebilirim . git checkoutçalışma ağacının güncellenmesi ve şu anda "seçili" dalın ( HEAD) değiştirilmesi ile ilgilidir.
Mikko Rantalainen

2
@MikkoRantalainen hayır. git reset% 100 hakkında HEAD. Ayrı bir HEAD modunda bile çalışır ( stackoverflow.com/a/3965714/6309 ), yani şube olmadığı yerde (!). git checkout ayrı bir HEAD modunda da çalışır ya da bir SHA1'i bağımsız HEAD modunda kontrol etmek için kullanılabilir: yine bu durumda herhangi bir dal bulunmamaktadır.
VonC

3
Burada bir arama motoru tarafından gönderilen tüm kayıp ruhlar için daha fazla okuma, buna değer olduğunu düşünüyorum: git-scm.com/blog/2011/07/11/reset.html
Thinkeye

2
@Thinkeye iyi referans. Daha fazla görünürlük için ilgili bir özü ile birlikte ekledim.
VonC

2
Demystified'i Sıfırla'nın açıklaması mükemmel. Bu cevabın ilk paragrafı yanıltıcıdır: "git checkout ... HEAD'ı sadece bir şubeye check-out yaparsanız güncelleyecektir (eğer değilse, ayrılmış bir HEAD ile sonuçlanırsınız)". Doğru değil ... git checkout , şube olmayan bir taahhütte bulunsanız bile HEAD'ı güncelleyecektir (ve evet, ayrılmış bir HEAD ile sonuçlanırsınız, ancak yine de güncellenmiştir). Belki "güncelleme" ile ne demek istediğini yanlış anlıyorum? git checkout a839e8fTaahhüt noktasını HEAD günceller a839e8f.
LarsH

67

En basit haliyle, resetçalışma ağacına dokunmadan dizini sıfırlarken, çalışma ağacını dizine dokunmadan checkoutdeğiştirir.

HEADÇalışma ağacını tek başına bırakacak şekilde dizini eşleşecek şekilde sıfırlar :

git reset

Kavramsal olarak, bu indeksi çalışma ağacına denetler. Herhangi bir şeyi yapmasını sağlamak için -f, herhangi bir yerel değişikliği üzerine yazmaya zorlamak için kullanmanız gerekir. Bu, "argüman yok" formunun yıkıcı olmadığından emin olmak için bir güvenlik özelliğidir:

git checkout

Parametreleri eklemeye başladıktan sonra, bazı örtüşme olduğu doğrudur.

checkoutgenellikle bir dal, etiket veya taahhütle kullanılır. Bu durumda HEAD, dizini sıfırlar ve dizini verilen işleme alır ve dizinin çalışma ağacına çıkışını gerçekleştirir.

Eğer tedarik Ayrıca, --hardiçin resetsorabilirsinreset çalışma ağaç üzerine yanı sıra dizinin sıfırlanması için.

Şimdiye kadar bir şubenizi kontrol ettirdiyseniz, alternatif bir şube veya taahhüt sağladığınız resetve checkoutne zaman verdiğiniz arasında çok farklı bir fark vardır . resetmevcut dalı seçilen taahhüdü gösterecek şekilde değiştirir, checkoutancak mevcut dalı yalnız bırakır, ancak bunun yerine verilen şubeyi teslim alır veya yerine geçer.

Diğer formlar resetvecommit yolları tedarik etmeyi içerir.

Yollar sağlıyorsanız reset, sağlayamazsınız --hardve resetyalnızca sağlanan yolların dizin sürümünü, sağlanan taahhütteki sürüme değiştirirseniz (veyaHEAD belirttiğiniz yoksa bir taahhüt).

İçin yol sağlıyorsanız checkout, resetsağlanan yolların dizin sürümünü sağlanan kesinleştirme (veya HEAD) ile eşleşecek şekilde günceller, ancak her zaman sağlanan yolların dizin sürümünü çalışma ağacına gönderir.


2
"Ödeme" nin dizini değiştirmediğini söylemek doğru değildir: bir şubeden diğerine gitmek için kullanıldığında bunu değiştirir.
wiki1000

En basit haliyle, reset işlemi çalışma ağacına dokunmadan dizini sıfırlarken, ödeme çalışma ağacını dizine dokunmadan değiştirir. : Bu ne kadar kafa karıştırıcı: |
Aditya Gupta

41

Değişikliği geri alırken basit bir kullanım örneği:
1. Değiştirilmiş bir dosyanın evrelemesini geri almak istiyorsanız sıfırlama işlevini kullanın.
2. Etiketlenmemiş dosya (lar) daki değişiklikleri silmek istiyorsanız, kasayı kullanın.


1
Mükemmel cevap. Teşekkür ederim.
user358591

11

Özetle, temel reset dal referansını hareket ettirirken,checkout hareket ettirmemesi (HEAD'ı hareket ettirmesi).

Pro Git kitabının Demystified'i Sıfırla bölümünde açıkladığı gibi ,

Yapılacak ilk şey reset, HEAD'in işaret ettiği şeyi taşımaktır . Bu HEAD'ın kendisini değiştirmekle aynı şey değildir (ki bu da checkoutöyle); HEAD'ın işaret reset ettiği dalı hareket ettirir . Bu, HEAD masterşubeye ayarlanmışsa (yani, şu anda masterşubedeyseniz), çalışmaya işaret ederek git reset 9e5e6a4başlayacağı anlamına mastergelir 9e5e6a4. [vurgu eklendi]

Çok yararlı bir metin ve şema alıntısı için VonC'nin cevabına da bakınız.Aynı makaleden yapmam gereken .

Tabii ki , hangi parametrelerin kullanıldığına bağlı olarak indeks ve çalışma ağacı üzerinde hangi etkilerin checkoutve neler resetolabileceğiyle ilgili çok daha fazla ayrıntı var . İki komut arasında birçok benzerlik ve farklılık olabilir. Ama gördüğüm gibi, en önemli fark, mevcut dalın ucunu hareket ettirip değiştirmedikleri.


2
Eski cevabımın yanı sıra iyi geribildirim. +1
VonC

2

İki komut (sıfırlama ve ödeme) tamamen farklıdır.

checkout X DEĞİL reset --hard X

X bir dal adı checkout Xise, geçerli dalı değiştirmez reset --hard X.


2
Ancak X bir dosya veya klasörse, aynıdır.
Ted Bigham

1

kısa anımsatıcılar:

git reset HEAD           :             index = HEAD
git checkout             : file_tree = index
git reset --hard HEAD    : file_tree = index = HEAD
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.