Git reset --mixed, --soft ve --hard arasındaki fark nedir?


741

Bir taahhüdü bölmek ve kullanmak için sıfırlama seçeneği emin değilim.

Sayfaya bakıyordum Düz İngilizce'de "git reset" ne yapar? , ama git indeksinin veya sahneleme alanının ne olduğunu gerçekten anlamadığımı fark ettim ve bu yüzden açıklamalar yardımcı olmadı.

Ayrıca, bu yanıtta kullanım durumları --mixedve --softbenim için aynı görünüyor (düzeltmek ve tavsiye etmek istediğinizde). Birisi daha da yıkabilir mi? Farkındayım --mixedmuhtemelen gitmek seçenek, ama ben bilmek istiyorum neden . Son olarak ne olacak --hard?

Birisi bana 3 seçeneğin nasıl seçileceğine dair bir iş akışı örneği verebilir mi?


1
Biraz daha açıklığa kavuşturmak için diğer sorudaki cevabımı düzenleyeceğim.
Cascabel

@mkarasek yanıtı oldukça iyi, ancak bu soruya da bakmak ilginizi çekebilir .
brandizzi

3
Kendine Not: Genel olarak , soft: stage everything, mixed: unstage everything, hard: ignore everythingtaahhüt kadar ben den sıfırlama ediyorum.
user1164937


David Zychaçık bir açıklama ile başka bir iyi makale - davidzych.com/difference-between-git-reset-soft-mixed-and-hard
src3369

Yanıtlar:


1489

Deponuzdaki bir dosyayı değiştirdiğinizde, değişiklik başlangıçta etiketsizdir. Taahhüt etmek için, kullanarak - yani dizine eklemeniz gerekir git add. Bir taahhütte bulunduğunuzda, taahhüt edilen değişiklikler dizine eklenen değişikliklerdir.

git reseten azından, geçerli dalın ( HEAD) işaret ettiği yerde değişir . Arasındaki fark --mixedve --softDizininizin da modifiye edilip değildir. Yani, masterbu taahhüt dizisi ile daldaysak:

- A - B - C (master)

HEADişaret eder Cve dizin eşleşir C.

Ne zaman biz koşmak git reset --soft B, master(ve böylece HEAD) şimdi işaret B, ama dizin hala değişiklikleri vardır C; git statusonları sahnelenmiş olarak gösterecektir. Yürüttüğümüz Yani git commitbu noktada, yeni bir aynı değişikliklerle taahhüt alırsınız C.


Tamam, tekrar buradan başlayarak:

- A - B - C (master)

Şimdi yapalım git reset --mixed B. (Not: --mixedvarsayılan seçenektir). Bir kez daha masterve HEADB'yi işaret edin, ancak bu sefer dizin de eşleşecek şekilde değiştirildi B. git commitBu noktada çalışırsak , dizin eşleştiğinden beri hiçbir şey olmaz HEAD. Çalışma dizininde hala değişiklikler var, ancak dizinde olmadıkları için git status, bunları etiketsiz olarak gösteriyor. Onları taahhüt etmek için, git addher zamanki gibi taahhüt ederdin .


Ve son olarak, --hardaynıdır --mixed(sizin değiştirir HEADdışında ve dizin) --hardayrıca çalışma dizinini değiştirir. Biz çalışıyor Cve çalıştırırsak git reset --hard B, eklenen değişiklikler Cve sahip olmadığınız tüm değişiklikler kaldırılacak ve çalışma kopyanızdaki dosyalar kesin olarak eşleşecektir B. Değişiklikleri bu şekilde kalıcı olarak kaybedebileceğiniz git statusiçin, çalışma dizininizin temiz olduğundan veya taahhüt edilmemiş değişikliklerinizi kaybetmekte uygun olduğunuzdan emin olmak için her zaman donanımdan sıfırlama yapmadan önce çalışmalısınız.


Ve son olarak, bir görselleştirme: resim açıklamasını buraya girin


45
Başka bir deyişle, --soft son taahhüdü atar, --mix son taahhüdü atar ve ekler, --hard son taahhüdü atar, git ve çıkış kodu ile aynı olan kodlarda yaptığınız değişiklikleri kaldırır HEAD
James Wang

11
@eventualEntropy Reflog ile taahhüt edilen değişiklikleri kurtarabilirsiniz ; ile kaldırılan taahhüt edilmemiş değişiklikler reset --hardsonsuza dek gider.
mkarasek

2
@Robert Hiçbiri; --mixeddizininizi değiştirir ancak çalışma dizininizi değiştirmez, bu nedenle yerel değişiklikler etkilenmez.
mkarasek

3
Terminalde git'i renkli kullanan görsel insanlar için yardımcı olabilir: 1.'git reset --soft A 've B ve C öğelerini yeşil (aşamalı) olarak göreceksiniz 2.'git reset - karışık A' ve göreceksiniz B ve C'nin öğelerini kırmızı renkte görebilirsiniz (etiketsiz) 3.'git sıfırlama --hard A 've artık B ve C'nin değişikliklerini hiçbir yerde görmeyeceksiniz (hiç
varmamışlar

2
@ user1933930 1 ve 3 sizi - A - B - C′C ile bırakacaktır , burada C C C ile aynı değişiklikleri içerir (farklı zaman damgası ve muhtemelen taahhüt mesajı ile). 2 ve 4 sizi bırakacaktır - A - D, burada D B ve C'nin birleşik değişikliklerini içerir.
mkarasek

215

En basit terimlerle:

  • --soft: uncommit değişiklikler, değişiklikler aşamalı olarak bırakılır ( dizin ).
  • --mixed (varsayılan) : uncommit + unstage değişiklikleri, değişiklikler çalışma ağacında bırakılır .
  • --hard: uncommit + unstage + değişiklikleri sil , hiçbir şey kalmadı.

8
en iyi cevap çünkü cevap aynı zamanda en özlü olan tam bir cevap sağlamak için teknik terimler kullanıyor
Trevor Boyd Smith

1
Bir dosyayı (unpushed) işlediğimde ve yeni oluşturulmuş izlenmeyen bir dosyam olduğunda, git reset --hard hiçbir şey yapmıyor mu? Yalnızca izlenmeyen dosyayı hazırladığımda dosyayı çalışma dizinimden kaldırır.
Michael

1
@Nikhil Bu cevabın nerede yanlış olduğunu açıklayabilir misiniz?
Ned Batchelder

1
@NedBatchelder Noktanın hiçbiri doğru değil: Çünkü bu komutlar kullanıldığında uncommit asla gerçekleşmez.
Nikhil

1
@Nikhil Belki de demek istediğin orijinal taahhüdün hala var olmasıdır, ki bu doğrudur. Ancak şube, taahhüt artık şubenin bir parçası olmayacak şekilde değiştirildi. Buna katılıyor muyuz?
Ned Batchelder

69

Bu karmaşık işlevselliği anlamak için ilk adım olarak tasarlanan basitleştirilmiş bir açıklama olduğunu lütfen unutmayın.

Bu komutların her birinin ardından proje durumlarının nasıl göründüğünü görselleştirmek isteyen görsel öğrenciler için yardımcı olabilir:


Terminali renk açıkken kullananlar için (git config --global color.ui auto):

git reset --soft A ve B ve C öğelerini yeşil renkte görürsünüz (sahnelendi ve işlemeye hazır)

git reset --mixed A(veya git reset A) ve B ve C öğelerini kırmızı olarak görürsünüz (işaretsiz ve sahnelenmeye hazır (yeşil) ve sonra işlenir)

git reset --hard A ve artık B ve C'nin değişikliklerini hiçbir yerde görmeyeceksiniz (hiç varmamışlar gibi olacak)


Veya 'Tower' veya 'SourceTree' gibi bir GUI programı kullananlar için

git reset --soft A ve B ve C öğelerini 'hazır dosyalar' alanında işlemeye hazır göreceksiniz

git reset --mixed A(veya git reset A) ve "etiketlenmemiş dosyalar" alanındaki B ve C öğelerini sahnelemeye ve sonra işlenmeye hazır olarak göreceksiniz

git reset --hard A ve artık B ve C'nin değişikliklerini hiçbir yerde görmeyeceksiniz (hiç varmamışlar gibi olacak)


1
Bu en iyi ihtimalle yanıltıcıdır: Cevabınız sanki çıktısının git resetgörünümünü değiştirmiş gibi okunur git status.
jub0bs

3
Demek istediğim, ama aynı fikirde değilim çünkü görsel bir öğrenci olarak, 3 komutu kullandıktan sonra projemin nasıl 'göründüğünü' görmek nihayet ne yaptıklarını anlamama yardımcı oldu!
timhc22

İnsanların gerçekte olanı rahatlatmasına yardımcı olmak için daha çok 'aptallar için git' fikrini gördüm. Yanıltıcı olmamak için nasıl geliştirilebileceğini düşünebilir misiniz
timhc22

8
Hayır, bu cevabı değiştirmemiz gerekmiyor. Kullanışlı bir "hile sayfası" sağlar. Bir düşünün: yumuşak = yeşil, karışık = kırmızı, sert = hiçbir şey (gitti anlamına gelir)! Hatırlaması ne kadar kolay! Bu rengin gerçekten ne anlama geldiğini bile anlamayan yeni başlayanlar için git hakkında çok az şey biliyorlar ve yine de yolda zor dersler alacaklar ve bu @unegma'nın hatası DEĞİL! BTW, bu cevabı önceki düşüşe karşı koymak için düzeltiyorum. Aferin, @unegma!
RayLuo

5
Bu, başka yerlerde okuduğum için iç çalışmaları daha iyi anlamak için harika bir tamamlayıcı özetti. Teşekkür ederim!
spex

24

Diğer tüm cevaplar harika, ama en iyisi üç kategoriye dosyalarını parçalayarak onları anlamaya bulmak: unstaged, staged, commit:

  • --hard anlaşılması kolay olmalı, her şeyi geri yükler
  • --mixed (varsayılan) :
    1. unstageddosyalar: değişme
    2. staged dosya: şuraya taşı unstaged
    3. commit dosya: şuraya taşı unstaged
  • --soft:
    1. unstageddosyalar: değişme
    2. stageddosyalar: değişiklik yapma
    3. commit dosya: şuraya taşı staged

Özetle:

  • --softseçeneği her şeyi ( unstageddosyalar hariç )staging area
  • --mixed seçeneği her şeyi içine taşıyacak unstaged area

22

İşte TortoiseGit kullanıcıları için temel bir açıklama:

git reset --softve --mixeddosyalarınıza dokunmayın.

git reset --hardAslında dosyalarınızı değiştirmek size sıfırlamak taahhüt eşleşecek.

TortoiseGit'te, dizin kavramı GUI tarafından çok gizlidir. Bir dosyayı değiştirdiğinizde git add, değişikliği hazırlama alanına / dizinine eklemek için çalıştırmanız gerekmez . Dosya adlarını değiştirmeyen git reset --softve --mixedaynı olan mevcut dosyalarda yapılan değişikliklerle uğraşırken ! Yalnızca yeni dosyalar eklediyseniz veya dosyaları yeniden adlandırdıysanız bir fark görürsünüz. Bu durumda, git reset --mixed komutunu çalıştırırsanız, Dosyalarınızı Sürüm Yok Dosyaları listesinden yeniden eklemeniz gerekir .


Bu cevap yumuşak ve karışık arasındaki farktan çok açık değil. ve bunu belirtmekte bile küçümser. Aşağıdaki cevap bu konuda daha açıktır. stackoverflow.com/questions/2530060/…
barlop

2
Aynı davranışa sahip olan Github Desktop'ın bir kullanıcısı olarak, bu cevap bana neden karıştığım konusunda netlik veriyor --mixedve --soft.
Chen Li Yong,

20

Bu durumlarda umarım bunu açıklayabilecek bir görseli severim:

git reset --[hard/mixed/soft] :

resim açıklamasını buraya girin

Yani her etki farklı kapsamlar

  1. Zor => WorkingDir + Dizin + KAFA
  2. Karışık => Dizin + KAFA
  3. Yumuşak => yalnızca HEAD (dizin ve çalışma dizisi değişmedi).

15

Üç çeşit pişmanlık

Mevcut cevapların çoğu gerçek soruya cevap vermiyor gibi görünüyor. Bunlar, komutların ne yaptığıyla ilgilidir, (kullanıcı) ne istediğinizle değil, kullanım senaryosuyla ilgilidir . Ama OP bu konuda sordu!

Komutu verdiğiniz sırada pişman olmanızın tam olarak ne olduğu konusunda açıklamayı saklamak daha yararlı olabilir git reset. Diyelim ki buna sahibiz:

A - B - C - D <- HEAD

İşte bazı olası pişmanlıklar ve onlar hakkında ne yapmalı:

1. B, C ve D'nin tek bir taahhüt olmadıkları için üzgünüm .

git reset --soft A. Ben şimdi hemen işleyebilir ve abra A beri tüm değişiklikleri vardır biri işlemek.

2. B, C ve D'nin on taahhüt olmadığı için üzgünüm .

git reset --mixed A. Taahhütler kayboldu ve endeks A'ya döndü, ancak çalışma alanı hala D'den sonra olduğu gibi görünüyor. Böylece şimdi tamamen farklı bir gruplamaya ekleyebilir ve işleyebilirim.

3. Bu dalda B, C ve D'nin gerçekleştiğine pişmanım ; Keşke A'dan sonra dallanmış olsaydım ve o dalda olmuşlardı.

Yeni bir dal yapın otherbranchve sonra git reset --hard A. Mevcut dal, şimdi A'da bitiyor ve otherbranchondan kaynaklanıyor.

(Elbette B, C ve D'nin hiç olmamasını istediğiniz için sert bir sıfırlama da kullanabilirsiniz.)


5

Aralarındaki farkları hatırlamak için kendinizi zorlamanız gerekmez. Gerçekte nasıl bir taahhütte bulunduğunuzu düşünün.

1.Bazı değişiklikler yapın.

2.git ekleyin.

3.gc -m "Bir Şey Yaptım"

Yumuşak, Karışık ve Sert, 3'ten 1'e kadar yaptığınız işlemleri bırakmanızı sağlayan yoldur.

"Gc -m" yaptığınızı hiç görmemek için yumuşak "numara yapmış".

Karışık "taklit" hiç görmedim görmek için "git add."

Dosya değişiklikleri yaptığınızı hiç görmemek zor "davrandı".


4

Bu üç seçeneğe girmeden önce 3 şeyi anlamalısınız.

1) Tarih / BAŞLIK

2) Aşama / dizin

3) Çalışma dizini

reset --soft: Geçmiş değişti, HEAD değişti, Çalışma dizini değişmedi.

reset --mixed: Geçmiş değişti, HEAD değişti, Çalışma dizini değişmemiş verilerle değişti.

reset --hard: Geçmiş değişti, HEAD değişti, Çalışma dizini kayıp verilerle değiştirildi.

Git --soft ile gitmek her zaman güvenlidir. Karmaşık gereksinimde başka bir seçenek kullanılmalıdır.


3

Burada yanlış bir anlayışla bir takım cevaplar var git reset --soft. git reset --softSadece HEAD(ayrı bir kafa durumundan başlayarak), tipik olarak (ve amaçlanan kullanım için) değişecek belirli bir durum olsa da, şu anda kontrol ettiğiniz dal referansını taşır. Tabii ki bir şubeniz yoksa bunu yapamaz (bu nedenle git reset --softsadece değişecek olan özel durum HEAD).

Bunu düşünmenin en iyi yolu olarak buldum git reset. Sadece hareket etmiyorsunuzHEAD ( her şey bunu yapıyor ), aynı zamanda şube ref'sini de hareket ettiriyorsunuz , örn master. Bu, çalıştırdığınızda olanlara benzer git commit(geçerli dal, birlikte HEADhareket eder), yeni bir taahhüt oluşturmak (ve ona geçmek) yerine, önceki bir taahhüde geçersiniz.

Bu, resetbir dalı yeni bir taahhütten başka bir şeye değiştirmek değil, değiştirmek anlamına gelir HEAD. Bunu dokümantasyon örneğinde görebilirsiniz:

Bir taahhüdü geri alma ve bir konu dalı yapma

          $ git branch topic/wip     (1)
          $ git reset --hard HEAD~3  (2)
          $ git checkout topic/wip   (3)
  1. Bazı taahhütler yaptınız, ama onların "usta" dalda olmak için erken olduklarını fark ettiniz. Onları bir konu dalında parlatmaya devam etmek istiyorsunuz, bu nedenle geçerli HEAD'den "topic / wip" dalı oluşturun.
  2. Bu üç taahhütten kurtulmak için ana dalı geri sarın.
  3. "Topic / wip" dalına geçin ve çalışmaya devam edin.

Bu komut dizisinin amacı nedir? Burada bir dalı taşımak istiyorsunuz master, bu yüzden mastercheck-out yaparken koşuyorsunuz git reset.

Buradaki en çok oy alan cevap genellikle iyidir, ancak birkaç yanıtı yanlış anlamalarla düzeltmek için bunu ekleyeceğimi düşündüm.

Şubenizi değiştirin

git reset --soft <ref>: halihazırda teslim alınmış olan şubenin şube işaretçisini belirtilen referanstaki işleme sıfırlar <ref>,. Çalışma dizininizdeki ve dizindeki dosyalar değiştirilmez. Bu aşamadan itibaren taahhütte bulunmanız sizi git resetkomuttan önceki konumunuza götürecektir .

Dizininizi de değiştirin

git reset --mixed <ref>

Veya eşdeğer olarak

git reset <ref>:

AND de ne --softyapar , belirtilen referanstaki taahhüdü eşleştirmek için dizini sıfırlar. İken (o dal teslim etmek şube teslim taşımak diyor çünkü) hiçbir şey yapmaz, veya eş anlamlı o senin son tamamlama durumuna endeksi sıfırlar nedeniyle, yaygın ve kullanışlı komuttur.git reset --soft HEADgit reset --mixed HEADgit reset HEAD

Çalışma dizininizi de değiştirin

git reset --hard <ref>: ne --mixedyapar VE AND çalışma dizininizin üzerine yazar. Bu komut, şubenin ref işaret ettiği tüm hareket biçimleriningit checkout <ref> dışında (ve bu çok önemli bir noktadır reset) benzerdir .git resetHEAD

"Böyle ve böyle bir komut HEAD'ı hareket ettirir" hakkında bir not:

Bir komutun HEAD. Komutunu taşıdığını söylemek yararlı değildir . İşlem geçmişinizde bulunduğunuz yeri değiştiren tüm komutlar HEAD. Yani ne HEAD olduğunu , nerede olursanız bir işaretçi. HEADsensin , ve ne zaman yaparsan o zaman hareket edeceksin.


2
"şube ref hareket": iyi bir nokta. Stackoverflow.com/a/5203843/6309 adresini güncellemem gerekti .
VonC

1

3 seçeneğin hangi bağlamda kullanıldığına dair kısa bir cevap:

Koddaki mevcut değişiklikleri korumak, ancak yürütme geçmişini yeniden yazmak için:

  • soft: Her şeyi bir kerede taahhüt edebilir ve yeni bir açıklama ile yeni bir taahhüt oluşturabilirsiniz (torotise git veya diğer birçok GUI'yi kullanıyorsanız, bunu kullanmak için olan addır, çünkü taahhütte hangi dosyaları işaretleyip birden fazla dosya oluşturabileceğinizi Sourcetree'de tüm dosyalar taahhüt için hazırlanır.)
  • mixed: Taahhütleri yapmadan önce tek tek dosyaları dizine tekrar eklemeniz gerekir (Sourcetree'de değiştirilen tüm dosyalar işaretlenmez)

Koddaki değişikliklerinizi gerçekten kaybetmek için :

  • hard: sadece geçmişi yeniden yazmakla kalmaz, aynı zamanda sıfırladığınız noktaya kadar tüm değişikliklerinizi kaybedersiniz

Bu durumda yumuşak ve karışık olmuyorum. Taahhüt etmek zorunda kalırsanız, o zaman geri döndürülen nedir? geri mi dönüyorsunuz yoksa değişiklikleri mi tavsiye ediyorsunuz (yani orijinal duruma geri dönüyor musunuz?)
John Little

Değişiklikleri tavsiye etmek. Ters bir taahhüt olmayacak.
Nickpick

1

Git reset komutunun çeşitli seçenekleri arasındaki temel fark aşağıdaki gibidir.

  • --soft: HEAD'i yalnızca seçtiğiniz işleme sıfırlar. Temelde git checkout ile aynı şekilde çalışır, ancak ayrılmış bir kafa durumu oluşturmaz.
  • --mixed (varsayılan seçenek): HEAD'i hem geçmişte seçtiğiniz taahhüde sıfırlar hem de dizindeki değişiklikleri geri alır.
  • --hard: HEAD'i hem geçmişte seçtiğiniz taahhüde sıfırlar, dizindeki değişiklikleri geri alır ve çalışma dizininizdeki değişiklikleri geri alır.

1

--soft: Git'e HEAD'i başka bir işleme sıfırlamasını söyler, böylece dizin ve çalışma dizini hiçbir şekilde değiştirilmez. Orijinal HEAD ve taahhüt arasında değişen tüm dosyalar hazırlanır.

--mixed: Tıpkı yazılım gibi, bu HEAD'i başka bir işleme sıfırlayacak. Ayrıca, çalışma dizinine dokunulmayacakken dizini eşleşecek şekilde sıfırlar. Tüm değişiklikler çalışma dizininde kalacak ve değiştirilmiş olarak görünecek, ancak aşamalı olarak görünmeyecektir.

--hard: Bu her şeyi sıfırlar - HEAD'i başka bir işleme geri döndürür, dizini eşleştirmek için sıfırlar ve çalışma dizinini de eşleştirmek için sıfırlar.

Arasındaki temel fark --mixedve --softDizininizin da modifiye edilip değildir. Bununla ilgili daha fazla bilgiyi burada bulabilirsiniz .


0

mkarasek'in Cevabı harika, basit bir deyişle diyebiliriz ...

  • git reset --soft: HEADhedeflenen taahhüdü ayarlayın ancak değişikliklerinizi son taahhütlerden itibaren hazır tutun
  • git reset --mixed: aynı git reset --softama tek fark, son taahhütlerden değişikliklerinizi aşamalı hale getirmektir
  • git reset --hard: HEADbelirttiğiniz taahhüdünüzü ayarlayın ve taahhüt edilmemiş değişiklikler de dahil olmak üzere son taahhütlerden tüm değişikliklerinizi sıfırlayın.
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.