Sade İngilizce'de “git reset” ne yapar?


674

Hakkında incelikleri açıklayan ilginç mesajlar gördüm git reset.

Ne yazık ki, ne kadar çok okursam, tam olarak anlamadığım o kadar fazla görünüyor. SVN geçmişinden geliyorum ve Git tamamen yeni bir paradigma. Kolayca cıva aldım, ama Git çok daha teknik.

Bence git resetyakın hg revert, ama görünüşe göre farklılıklar var.

Peki tam olarak ne git resetyapıyor? Lütfen aşağıdakilerle ilgili ayrıntılı açıklamalar ekleyin:

  • seçenekleri --hard, --softve --merge;
  • Eğer kullandığınız garip gösterimi HEADgibi HEAD^ve HEAD~1;
  • somut kullanım durumları ve iş akışları;
  • çalışma kopyası üzerindeki sonuçları HEADve küresel stres seviyeniz.

17
Bence Visual Git Reference ortak git komutlarını kullanırken neler olduğu konusunda iyi bir fikir veriyor.

Yanıtlar:


992

Genel olarak, git resetişlevi geçerli dalı alıp başka bir yere işaret edecek şekilde sıfırlamak ve büyük olasılıkla dizin ve çalışma ağacını yan yana getirmektir. Daha somut olarak, ana dalınız (şu anda teslim alınmış) şu şekildeyse:

- A - B - C (HEAD, master)

ve ustanın C'yi değil B'yi göstermesini istediğinizi fark edersiniz, git reset Boraya taşımak için kullanırsınız :

- A - B (HEAD, master)      # - C is still here, but there's no branch pointing to it anymore

Digression: Bu bir ödeme işleminden farklı. Eğer git checkout Bkoşsaydın şunu elde edersin:

- A - B (HEAD) - C (master)

Sonunda bağımsız bir HEAD durumuna geldiniz. HEAD, çalışma ağacı, dizinde tüm maç B, ancak ana şube geride kaldı C. DBu noktada yeni bir taahhütte bulunursanız , bunu elde edersiniz, bu muhtemelen istediğiniz şey değildir:

- A - B - C (master)
       \
        D (HEAD)

Unutmayın, sıfırlama işleminin taahhütte bulunmadığını, yalnızca farklı bir taahhüdü işaret edecek bir dalı (bir taahhüdün göstergesidir) günceller. Gerisi sadece endeksinize ve çalışma ağacınıza ne olduğuna dair detaylar.

Kullanım örnekleri

Bir git resetsonraki bölümdeki çeşitli seçeneklerin açıklamalarım dahilinde ana kullanım durumlarının çoğunu ele alıyorum. Gerçekten çok çeşitli şeyler için kullanılabilir; ortak iş parçacığı, hepsinin belirli bir taahhüdü işaret etmek / eşleştirmek için şube, dizin ve / veya çalışma ağacını sıfırlamayı içermesidir.

Dikkat edilmesi gerekenler

  • --hardişinizi gerçekten kaybetmenize neden olabilir. Çalışma ağacınızı değiştirir.

  • git reset [options] committaahhütleri kaybetmenize (bir nevi) neden olabilir. Yukarıdaki oyuncak örneğinde, taahhüdü kaybettik C. Hala depoda ve git reflog show HEADya da bakarak bulabilirsiniz git reflog show master, ama artık herhangi bir şubeden erişilebilir değil.

  • Git bu tür taahhütleri 30 gün sonra kalıcı olarak siler, ancak o zamana kadar C'yi bir şubeyi tekrar işaretleyerek kurtarabilirsiniz ( git checkout C; git branch <new branch name>).

Argümanlar

Man sayfasını açıklayan en yaygın kullanım, git reset [<commit>] [paths...]verilen yolların belirli bir taahhütten durumlarına sıfırlanacağı formdur . Yollar sağlanmazsa, tüm ağaç sıfırlanır ve taahhüt sağlanmazsa, HEAD (geçerli taahhüt) olarak alınır. Bu, git komutlarında (örn. Tam anlambilim farklı olsa da checkout, diff, log) yaygın bir kalıptır, bu yüzden çok şaşırtıcı olmamalıdır.

Örneğin, git reset other-branch path/to/foo/ dalında / foo yolundaki her şeyi diğer daldaki durumuna git reset -- .sıfırlar, geçerli dizini HEAD'deki durumuna git resetsıfırlar ve basit olan her şeyi HEAD'deki durumuna sıfırlar.

Ana çalışma ağacı ve dizin seçenekleri

Sıfırlama sırasında çalışma ağacınıza ve dizine ne olacağını kontrol etmek için dört ana seçenek vardır.

Unutmayın, endeks git'in "sahneleme alanı" dır - git addtaahhütte bulunmaya hazırlanırken söylediğiniz şey orasıdır.

  • --hardher şeyi sıfırladığınız işlemle eşleştirir. Muhtemelen anlaşılması en kolay olan budur. Tüm yerel değişiklikleriniz hızlanır. Birincil kullanım, işinizi havaya uçurmak, ancak anahtarları değiştirmemek git reset --harddemektir : git reset --hard HEADyani şubeyi değiştirmeyin, tüm yerel değişikliklerden kurtulun. Diğeri ise bir dalı bir yerden başka bir yere taşımak ve dizin / çalışma ağacını senkronize tutmak. Bu, gerçekten işinizi kaybetmenizi sağlayacak olanıdır, çünkü çalışma ağacınızı değiştirir. Çalıştırmadan önce yerel işleri atmak istediğinizden çok emin olun reset --hard.

  • --mixedvarsayılan, yani git resetanlamına gelir git reset --mixed. Dizini sıfırlar, ancak çalışma ağacını sıfırlamaz. Bu, tüm dosyalarınızın bozulmamış olduğu anlamına gelir, ancak orijinal işlem ile sıfırladığınız dosya arasındaki farklar git durumuna sahip yerel değişiklikler (veya izlenmemiş dosyalar) olarak görünür. Bunu bazı kötü taahhütlerde bulunduğunuzu fark ettiğinizde kullanın, ancak yaptığınız tüm işleri tutmak ve düzeltmek için devam etmek istiyorsunuz. Taahhüt etmek için dizine tekrar dosya eklemeniz gerekir ( git add ...).

  • --softdizine veya çalışma ağacına dokunmaz . Tüm dosyalarınız olduğu gibi sağlamdır --mixed, ancak tüm değişiklikler changes to be committedgit durumundaki gibi görünür (yani, işleme hazırlanırken kontrol edilir). Bazı kötü taahhütlerde bulunduğunuzu fark ettiğinizde bunu kullanın, ancak işin hepsi iyi - tek yapmanız gereken farklı bir şekilde tavsiye etmektir. Dizine dokunulmaz, böylece isterseniz hemen taahhütte bulunabilirsiniz - sonuçta elde edilen taahhüt, sıfırlamadan önce bulunduğunuz içerikle aynı olacaktır.

  • --mergekısa süre önce eklendi ve başarısız bir birleştirmeyi iptal etmenize yardımcı olmayı amaçlıyor. Bu gereklidir, çünkü git mergeaslında bu değişiklikler birleştirme işleminden etkilenmeyen dosyalarda olduğu sürece kirli bir çalışma ağacıyla (yerel değişikliklerle bir) birleştirmeye çalışmanıza izin verir. git reset --mergedizini sıfırlar ( --mixedtüm değişiklikler yerel değişiklikler olarak görünür ) ve birleştirme işleminden etkilenen dosyaları sıfırlar, ancak diğerlerini yalnız bırakır. Bu, umarım her şeyi kötü birleşmeden önceki haline geri getirir. Genellikle git reset --merge(anlam git reset --merge HEAD) olarak kullanırsınız çünkü aslında birleştirme işlemini sıfırlamak istiyorsunuz, aslında kolu hareket ettirmiyorsunuz. ( HEADbirleştirme başarısız olduğu için henüz güncellenmedi)

    Daha somut olmak için, A ve B dosyalarını değiştirdiğinizi ve C ve D dosyalarını değiştiren bir dalda birleştirmeye çalıştığınızı varsayalım. Birleştirme bir nedenle başarısız olur ve iptal etmeye karar verirsiniz. Sen kullan git reset --merge. C ve D'yi bulundukları yere geri getirir HEAD, ancak birleştirme girişiminin bir parçası olmadığı için değişikliklerinizi yalnızca A ve B'ye bırakır.

Daha fazla bilmek ister misiniz?

Bunun man git resetiçin gerçekten çok iyi olduğunu düşünüyorum - belki de git onlar için gerçekten olsa batmak için çalışıyor yolu biraz bir his gerekir. Özellikle, dikkatlice okumak için zaman ayırırsanız, çeşitli seçenekler ve durumlar için dizin ve çalışma ağacındaki dosyaların durumlarını detaylandıran bu tablolar çok yararlıdır. (Ama evet, çok yoğundurlar - yukarıdaki bilgilerin çok büyük bir kısmını çok özlü bir şekilde aktarmaktadırlar.)

Garip gösterim

Bahsettiğiniz "garip gösterim" ( HEAD^ve HEAD~1), gibi bir karma adı kullanmak zorunda kalmadan, taahhütleri belirtmek için bir kısayoldur 3ebe3f6. Git-rev-ayrıştırma için man sayfasının "revizyonları belirleme" bölümünde , birçok örnek ve ilgili sözdizimiyle tam olarak belgelenmiştir . Şapka ve tilde aslında farklı şeyler ifade eder :

  • HEAD~kısaltmasıdır HEAD~1ve işlemin ilk ebeveyni anlamına gelir. HEAD~2, söz konusu taahhüdün ilk ebeveyninin ilk ebeveynidir. HEAD~n"HEAD'den önce n taahhütte bulunur" veya "HEAD'in n'inci nesil atası" olarak düşünün .
  • HEAD^(veya HEAD^1) aynı zamanda taahhüdün ilk ebeveyni anlamına gelir. HEAD^2Taahhüdün ikinci ebeveyni anlamına gelir . Unutmayın, normal birleştirme taahhüdünün iki ebeveyni vardır - ilk veli birleştirilen taahhüttür ve ikinci veli birleştirilen taahhüttür. Genel olarak, birleşmelerin keyfi olarak birçok ebeveyni olabilir (ahtapot birleşmeleri).
  • ^Ve ~operatörler olarak, Yan yana dizilmiş olabilir HEAD~3^2, üçüncü nesil atası ikinci üst HEAD, HEAD^^2birinci ebeveyn ikinci üst HEADdüzgün ya da HEAD^^^denktir, HEAD~3.

düzeltme işareti ve dalga işareti


"oraya taşımak için git reset kullanacaksın." neden git checkout'u kullanmıyorsun?
e-satis

5
@ e-satis: git kasası HEAD'ı taşıyacak, ancak şubeyi olduğu yerde bırakacaktır. Bu, dalı taşımak istediğiniz zaman içindir.
Cascabel

Eğer iyi anlarsam, sıfırlama B şunu yapardı: - A - B - C - B (master) ödeme yaparken B - A - B (master)?
e-satis

32
dokümanlar onları okumak sonsuza dek sürse ve çok yoğun olsalar bile iyidir ve nasıl çalıştığını zaten biliyormuşsunuz gibi çalıştıklarını söylediklerini doğrulamak sonsuza kadar sürer. Dokümanlar benim için iyi gibi gelmiyor ...
Kirby

4
Bu SO cevabı ile çok basit ve anlaşılır bir açıklama verilir: stackoverflow.com/questions/3528245/whats-the-difference-between-git-reset-mixed-soft-and-hard
Nitin Bansal

80

İçinizde şunu unutmayın git:

  • HEADişaretçi üzerinde çalıştığınız işlemek söyler,
  • çalışma ağaç sisteminizdeki dosyaların durumunu temsil eder
  • ortaya koyma alanı (diğer adıyla endeks daha sonra birlikte işlediği böylece değiştirir "aşamaları")

Lütfen aşağıdakilerle ilgili ayrıntılı açıklamalar ekleyin:

--hard, --softVe --merge;

Tehlikeliğin artan düzeninde:

  • --softhareket eder, HEADancak hazırlama alanına veya çalışma ağacına dokunmaz.
  • --mixedHEADhazırlama alanını taşır ve günceller, ancak çalışma ağacını güncellemez.
  • --mergeçalışma HEADalanını taşır , sıfırlar ve çalışma ağacınızdaki tüm değişiklikleri yeni çalışma ağacına taşımaya çalışır.
  • --hardevreleme alanınızı ve çalışma ağacınızı her şeye atarak hareket ettirir HEAD ve ayarlar HEAD.

somut kullanım durumları ve iş akışları;

  • --softBaşka bir işleme geçmek ve "yerinizi kaybetmeden" şeyleri düzeltmek istediğinizde kullanın . Buna ihtiyacınız oldukça nadirdir.

-

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

-

  • --mixedBaşka bir işlemde işlerin nasıl göründüğünü görmek istediğinizde (varsayılan olan) kullanın , ancak zaten yaptığınız değişiklikleri kaybetmek istemezsiniz.

  • --mergeYeni bir noktaya gitmek istediğinizde kullanın , ancak zaten sahip olduğunuz değişiklikleri o çalışma ağacına dahil edin.

  • Kullanım --hardherşeyi silip yeni taahhüt taze bir barut başlatın.


2
Amaçlanan kullanım durumu bu değildir reset --merge. Üç yönlü birleştirme yapmaz. Bu, yalnızca dokümanlarda açıklandığı gibi, çakışan birleştirmelerin sıfırlanması içindir. checkout --mergeBahsettiğiniz şeyi yapmak için kullanmak isteyeceksiniz . Şube de taşımak istiyorsanız, bence tek yol onu sürüklemek için bazı ödeme / sıfırlama ile takip etmektir.
Cascabel

@Jefromi »Evet, bunu çok iyi ifade etmedim. "Yeni bir nokta" derken "çatışan birleşmenin olmadığı taze bir yer" demek istedim.
John Feminella

1
Ah, anlıyorum. Sanırım burada önemli olan şey, ne yaptığınızı gerçekten bilmediğiniz sürece, muhtemelen reset --merge(varsayılan) dışında herhangi bir hedefle kullanmak istemezsiniz HEAD, çünkü çakışan bir birleştirmeyi iptal etmenin yanı sıra, başka türlü kaydedebileceğiniz bilgiler.
Cascabel

2
Bu cevabı en basit ve en yararlı
buldum

Lütfen şu komutlar hakkında bilgi ekleyin: git resetve git reset -- ..
Flimm

35

Sonrası Demystified Sıfırlama blog Pro Git çok verir no-beyin üzerinde açıklama git resetve git checkout.

Bu yazının üstündeki tüm yararlı tartışmalardan sonra, yazar kuralları aşağıdaki üç basit adıma indirir:

Temelde bu. resetKomut siz söyleyinceye zaman durdurma, belirli bir sırada bu üç ağaç üzerine yazar.

  1. HEAD'ın işaret ettiği herhangi bir kolu taşıyın (eğer durursa --soft)
  2. Daha sonra, Endeks'in böyle görünmesini sağlayın (sürece burada durun --hard)
  3. O zaman, Çalışma Dizini'nin böyle görünmesini sağlayın

Ayrıca --mergeve --keepseçenekler var, ama şimdilik daha basit olmayı tercih ederim - bu başka bir makale için olacak.


25

Git için bir şey yaptığınızda, önce değişikliklerinizi aşamalandırmanız (dizine eklemeniz) gerekir. Bu, git onları bu taahhüdün bir parçası olarak görmeden önce bu işleme dahil etmek istediğiniz tüm dosyaları eklemeniz gerektiği anlamına gelir. Önce bir git repo imajına bir göz atalım: resim açıklamasını buraya girin

şimdi basit. Çalışma dizininde çalışmak, dosya, dizin oluşturmak ve her şeyi yapmak zorundayız. Bu değişiklikler izlenmeyen değişikliklerdir. İzlenmesi için git add komutunu kullanarak git dizinine eklememiz gerekir . Git dizinine eklendikten sonra. Artık git deposuna göndermek istiyorsak, bu değişiklikleri yapabiliriz.

Ama birdenbire, endeksine eklediğimiz fazladan bir dosyamızın git deposunu zorlamaya gerek olmadığını anlayarak öğrendik. Bu, dosyayı dizinde istemediğimiz anlamına gelir. Şimdi soru kullandığımız beri git indeksi o dosyayı kaldırmak için nasıl git eklenti kullanmak mantıklı olacaktır endeksinde onları koymak git rm ? Yanlış! git rm dosyayı siler ve silme işlemini dizine ekler. Peki şimdi ne yapmalı:

Kullanın: -

git reset

Dizininizi temizler, çalışma dizininize dokunulmaz. (sadece herşeyi bozmadan).

Onunla birçok seçenek ile kullanılabilir. Git reset ile kullanmak için üç ana seçenek vardır : --hard, --soft ve --mixed . Bunlar, sıfırladığınızda HEAD işaretçisine ek olarak nelerin sıfırlandığını etkiler.

İlk olarak, --hard her şeyi sıfırlar. Geçerli dizininiz, bu dalı tümüyle takip ediyor olsaydınız olduğu gibi olurdu. Çalışma dizini ve dizin bu işleme dönüştürülür. Bu en sık kullandığım versiyon. git reset --hard svn revert gibi bir şey .

Ardından, tam tersi —soft , çalışma ağacını veya dizini sıfırlamaz. Sadece HEAD işaretçisini hareket ettirir. Bu, geçerli durumunuzu dizininizde uyguladığınız taahhütten farklı olarak değiştirir ve işlemek için “hazırlanır”. Yerel olarak bir taahhütte bulunursanız ancak taahhüdü git sunucusuna göndermediyseniz, önceki taahhüdüne sıfırlayabilir ve iyi bir taahhüt mesajı ile tavsiye edebilirsiniz.

Son olarak, --mixed dizini sıfırlar, ancak çalışma ağacını sıfırlamaz. Yani değişikliklerin hepsi hala orada, ancak “etiketsiz” ve git add'ed veya git commit -a olması gerekiyor . Git komut -a ile istediğimizden daha fazlasını taahhüt ettiğimizde bunu bazen kullanırız, git reset --mixed ile taahhüdü geri alabilir, taahhüt etmek istediğimiz şeyleri ekleyebilir ve sadece bunları taahhüt edebiliriz.

Git revert ve git reset arasındaki fark : -


Basit bir deyişle, git reset "tamamlanmamış hataları düzelt" komutudur ve git geri döndürme "düzeltilmiş hata düzeltildi" komutudur .

Bu, bazı değişikliklerde bir hata yapmış ve aynı şeyi git repo'ya itmiş olsaydık, git revert'in çözüm olduğu anlamına gelir. Ve aynı hatayı itmeden / teslim etmeden önce belirlersek , sorunu çözmek için git reset komutunu kullanabiliriz .

Umarım karışıklığınızdan kurtulmanıza yardımcı olur.


2
OP tarafından sorulduğu gibi güzel bir düz İngilizce cevap budur.
Episodex

1
Cevabında bunu özlememe rağmen. Nedir git reset HEADvarsayılan olarak? --hard, --softveya --mixed? Harika cevap btw.
giannis christofakis

1
Harika bir yanıt, ancak git reset --hardbazı verileri kaybetmenize neden olacak daha açık hale getireceğim . Ve yanlış olabilecek bir nokta var (% 100 emin değilim ... Hâlâ öğreniyorum!): --mixedSöylemek senin hakkında "Git taahhüt -a ile kastettiğimizden daha fazlasını yaparsak bunu bazen kullanırız" der. Şunu mu demek istediniz: "Eğer istediğimizden daha fazla sahneleysekgit stage . "? Gerçekten bunu taahhüt ettiyseniz, çok geç olduğunu düşünüyorum (sonunda söylediğiniz gibi, git reset "tamamlanmamış hataları düzeltmek için bir komuttur")
Fabio, Reinstate Monica'yı

6

TL; DR

git resetEvrelemeyi son işleme sıfırlar. --hardÇalışma dizininizdeki dosyaları son işleme sıfırlamak için de kullanın .

DAHA UZUN SÜRÜM

Ancak bu açıkça basittir, bu yüzden oldukça ayrıntılı cevaplar vardır. git resetDeğişiklikleri geri alma bağlamında okumak benim için daha anlamlı oldu . Örneğin şunu görün:

Git geri alma değişiklikleri geri almanın “güvenli” bir yoluysa, git reset'i tehlikeli yöntem olarak düşünebilirsiniz. Git reset ile geri alırsanız (ve komutlara artık herhangi bir ref veya reflog tarafından başvurulmaz), orijinal kopyayı almanın bir yolu yoktur; bu kalıcı bir geri alma işlemidir. İşinizi kaybetme potansiyeline sahip tek Git komutlarından biri olduğu için bu aracı kullanırken dikkatli olunmalıdır.

Gönderen https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

ve bu

İşleme düzeyinde, sıfırlama, bir dalın ucunu farklı bir işleme geçirmenin bir yoludur. Bu, geçerli daldaki taahhütleri kaldırmak için kullanılabilir.

Gönderen https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations


2

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

Checkout, belirli bir taahhütte başı işaret eder.

Sıfırlama, bir dalı belirli bir işlemde gösterir. (Dal, bir taahhüdün göstergesidir.)

Bu arada, eğer kafanız bir dalın da işaret ettiği bir taahhüdü işaret etmiyorsa, o zaman bağımsız bir kafanız vardır. (yanlış olduğu ortaya çıktı. Yorumlara bakın ...)


1
Değil nitpick, ama (evet, aslında bir kusur arayan ama hadi tamamlanması için ekleyin) senin 3 cümle teknik olarak yanlıştır. Diyelim ki HEAD, B dalını gösteriyor ve bu da abc123'ü taahhüt ediyor. Şimdi abc123 taahhüdünü kontrol ederseniz, HEAD ve şube B'nin her ikisi de abc123 taahhüdünü gösteriyor ve HEAD'iniz ayrılıyor. Bu noktada Committing olacak değil şube B'nin konumunu güncelleyin. "Eğer kafanız bir kolu işaret etmiyorsa, müstakil bir kafanız var demektir"
diyebilirdiniz

@RomainValeri Bu durumda ne yapacaksınız?
Ian Warburton

1
Taahhüt, herhangi bir şube tarafından referans verilmeyen taahhütler yaratacaktır ve B dalı, bundan sonra birkaç kez taahhüt ettikten sonra bile aynı taahhüt abc123'ü işaret etmeye devam edecektir. HEAD bu 'vahşi' dizi serilerindeki son taahhüdü işaret etmeyi bıraktığında, bu taahhütlerin çöp toplama adayı olacağı anlamına gelir.
RomainValeri
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.