Git komutunu silebilir miyim, ancak değişiklikleri koruyabilir miyim


1055

Geliştirme şubelerimden birinde, kod tabanımda bazı değişiklikler yaptım. Üzerinde çalıştığım özellikleri tamamlayabilmek için mevcut şubemi bazı özelliklerin tanıtımını yapmak için ustalaşmak zorunda kaldım. Ama sadece bir "git checkout master" ı kullanmak, geliştirme branşımda da yaptığım değişiklikleri koruyarak master'daki bazı işlevleri bozdu. Yaptığım şey, geliştirme şubemdeki değişiklikleri "geçici olarak kesinleştirme" ve ardından demo için ödeme yöneticisi ile tamamlamaktı.

Demoyu bitirdim ve geliştirme dalımda çalışmaya geri döndüğüme göre, yaptığım değişiklikleri korurken yaptığım "geçici taahhüdü" kaldırmak istiyorum. Mümkün mü?


65
Gelecek sefer:git stash
Matt Ball

51
@MattBall, ille de değil. git stashİyi bir araç olsa da, "devam etmekte olan çalışma" atma taahhütleri de oldukça meşru bir cihazdır.
kostix

3
Bu
Github'dan

9
@MattBall @kostix Evet, tüm repo için küresel bir yığın olduğu göz önüne alındığında, stash özellikle "uzun vadeli" stash için uygun değildir. Bir daldaki değişiklikleri saklamak ve daha sonra başka dallara gitmek, başka her şeyi yapmak, günler sonra git stasharadaki başka bir dalda kullanmış olabileceğimden endişe etmeden geri dönmek istiyorum .
Alec

4
Dikkate değer bir şey stash, tamamen yerel olması ve repo-silme veya rekreasyon veya donanım arızası veya kaybından kaynaklanan kod kaybına eğilimli olmasıdır. IMO, gerçekten sadece çok kısa süreli WIP için kullanılmalıdır. Tatile çıkmadan önce bir Devam Eden Çalışma taahhüdünü sevin: P .. bir beyin dökümü taahhüdü deyin!
ϲοδεMεδιϲ

Yanıtlar:


1617

Bu kadar basit:

git reset HEAD^

Not: bazı kabuklar ^özel bir karakter olarak işlev görür (örneğin, bazı Windows kabukları veya globbing etkinken ZSH ), "HEAD^"bu durumda alıntı yapmanız gerekebilir .

git resetBir olmadan --hardveya --softhamle HEADherhangi bir dosya değiştirmeden, belirtilen işlemeye işaret etmek. HEAD^şu anki taahhüdünüzün (ilk) ana taahhüdünü ifade eder, bu durumda davanız geçici olandan önceki taahhüttür.

Başka bir seçeneğin normal olarak devam etmek olduğunu ve ardından bir sonraki işlem noktasında çalışacağını unutmayın:

git commit --amend [-m … etc]

bunun yerine , yukarıdaki ile aynı etkiye sahip olan en son taahhüdü düzenler .

Bu (neredeyse her git cevabında olduğu gibi), kötü taahhüdü başka birinin çekmiş olabileceği bir yere zaten ittiyseniz sorunlara neden olabileceğini unutmayın. Bundan kaçınmaya çalışın


47
Bu en basit olanıdır, ancak taahhüdünüzü zaten bir uzaktan kumandaya ittiyseniz ve başka biri onu çekti, özür dilemek dışında bir şey yapmakta çok tereddüt ederdim.
atw13

11
@sicophrenic, bu vesileyle "Demystified Reset" okumak için fırsatı kaçırmayın .
kostix

33
Bunu More?yaptıktan sonra anladım . Bu istemde ne fatal: ambiguous argument 'HEADwhateverItypedIn': unknown revision or path not in the working tree.
yazıyorsam

50
@DaAwesomeP ^, özel bir karakter gibi davranan bir kabuk kullandığınızı duyuyor . Ya referans teklifi verebilir "HEAD^"alternatif sözdizimi veya kullanmak HEAD~1tırnak içine
Gareth

8
Benim için çalıştı, olsa karakter kaçmak zorunda kaldıgit reset HEAD\^
cevaris

188

Bunu ele almanın iki yolu vardır. Hangisi daha kolay durumunuza bağlıdır

Sıfırla

Eğer kurtulmak istediğiniz taahhüt son taahhüt ise ve herhangi bir ek iş yapmadıysanız, sadece git-reset

git reset HEAD^

Şubenizi mevcut BAŞKANIZIN hemen öncesine götürür. Ancak, aslında çalışma ağacınızdaki dosyaları değiştirmez. Sonuç olarak, bu işlemde yapılan değişiklikler değiştirilmiş olarak görünür - bu bir 'devre dışı bırak' komutu gibidir. Aslında, bunu yapmak için bir takma adım var.

git config --global alias.uncommit 'reset HEAD^'

O zaman git uncommitgelecekte sadece bir taahhüdü yedeklemek için kullanabilirsiniz.

Ezici

Bir taahhüdün ezilmesi, iki veya daha fazla taahhüdü bir araya getirmek anlamına gelir. Bunu oldukça sık yapıyorum. Sizin durumunuzda tamamlanmış bir yarı özelliğiniz var ve daha sonra onu bitirip uygun, kalıcı taahhüt mesajı ile tekrar taahhüt edersiniz.

git rebase -i <ref>

Yukarıda söylüyorum, çünkü bunun herhangi bir sayıda komisyon olabileceğini açıkça belirtmek istiyorum. git logKurtulmak istediğiniz taahhüdü çalıştırın ve bulun, SHA1'ini kopyalayın ve yerine kullanın <ref>. Git sizi etkileşimli rebase moduna geçirecektir. Mevcut durumunuz ile yerine koyduğunuz her şey arasındaki tüm taahhütleri gösterecektir <ref>. Bu yüzden <ref>10 işlemden önce, size 10 işlemin tümünü gösterecektir.

Her bir taahhüdün önünde kelimesi olacaktır pick. Eğer kurtulmak ve onu değiştirmek istiyorum taahhüt bul pickiçin fixupya squash. Kullanarak, fixupyalnızca iletiyi yürüten ve değişiklikleri listedeki selefi ile birleştiren atar. squashAnahtar kelime aynı şeyi yapar, ama yeni kombine taahhüt mesajını işlemek düzenleme olanağı sağlar.

Düzenleyiciden çıktığınızda işlemlerin listede göründükleri sırayla yeniden işleneceğini unutmayın. Bu nedenle, geçici bir taahhütte bulunduysanız, aynı dalda başka işler yaptıysanız ve özelliği daha sonraki bir taahhütte tamamladıysanız, rebase'i kullanmak taahhütleri yeniden sıralamanıza ve ezmenize izin verir.

UYARI:

Yeniden pazarlama geçmişi değiştirir - bunu başka geliştiricilerle paylaştığınız tüm taahhütlere DONT yapmayın.

stashing

Gelecekte, bu sorunu önlemek için, git stashtaahhüt edilmemiş işleri geçici olarak saklamak için kullanmayı düşünün .

git stash save 'some message'

Bu, mevcut değişikliklerinizi saklamak listenizdeki tarafa kaydeder. Yukarıda stash komutunun en açık versiyonu bulunmakta olup, ne sakladığınızı açıklayan bir yorum bulunmaktadır. Ayrıca basitçe çalıştırabilirsiniz git stashve başka bir şey yoktur, ancak hiçbir mesaj depolanmaz.

Saklamak listenize göz atabilirsiniz ...

git stash list

Bu size tüm zuhalarınızı, hangi dallarda yapıldıklarını ve her satırın başlangıcını ve mesajını ve stash@{#}# gibi bir zuvanın tanımlayıcısını gösterecektir.

Bir zulayı geri yüklemek için (hangi zuvanın orijinal olarak yaratıldığına bakılmaksızın herhangi bir dalda yapılabilir) sadece çalıştırın ...

git stash apply stash@{#}

Yine, # yığın dizisinde konum var. Geri yüklemek istediğiniz zift 0konumdaysa - yani, en son zudaysa. Daha sonra sadece stash konumunu belirtmeden komutu çalıştırabilirsiniz, git sonuncuyu kastettiğinizi varsayar git stash apply.

Yani, örneğin, kendimi yanlış dalda çalışırken bulursam - aşağıdaki komut dizisini çalıştırabilirim.

git stash
git checkout <correct_branch>
git stash apply

Sizin durumunuzda dallarda biraz daha hareket ettiniz, ancak aynı fikir hala geçerli.

Bu yardımcı olur umarım.


6
git config --global alias.uncommit reset HEAD^sadece takma ad sıfırlama işleminden çıkar. Bunun yerine, yapıngit config --global alias.uncommit 'reset HEAD^'
mernst

3
Windows komut isteminde kullanılıyorsa ^ yerine ^^ kullanmanız gerekeceğini unutmayın.
Pramod BR

106

Bence bunu arıyorsun

git reset --soft HEAD~1

Evrelemede yapılan değişiklikleri korurken en son taahhüdü geri alır.


7
Teşekkürler. Bu benim için çalıştı. git reset HEAD^Windows'da arama yapmak yalnızca "Daha fazla?" - ne anlama
Tyron

12
@Tyron DOS'ta ^bir kaçış karakteri. Yeni bir satırla eşleştirildiğinde, önceki komut için bir devam istemi görevi görür. Yazma git reset HEAD^^Windows'ta çalışmalıdır.
trk

40

Evet, değişiklikleri silmeden taahhüdünüzü silebilirsiniz: git reset @ ~


7
Bu gerçekten istediğim şey ve bence kabul edilen cevap, çok teşekkürler!
Carlos Liu

2
İlginç, kompakt sözdizimi, daha önce görmedim veya kullanmadım. Bunun git reset --softveya ' dan farkı git reset --keepnedir?
user776686

18

İkisinden birini git reset HEAD^ --softveya git reset HEAD^ --mixed.

Dokümanlarda belirtildiği gibi reset komutunun 3 modu vardır :

git reset HEAD^ --soft

geri al git commit. Çalışma ağacında (proje klasörü) + dizinde (--cached) değişiklikler hala var

git reset HEAD^ --mixed

git commit+ geri al git add. Çalışma ağacında hala değişiklikler var

git reset HEAD^ --hard

Kod tabanında bu değişiklikleri hiç yapmadığınız gibi. Değişiklikler çalışma ağacından gider.


9

Zsh kullananlar için aşağıdakileri kullanmanız gerekir:

git reset --soft HEAD\^

Burada açıklanmıştır: https://github.com/robbyrussell/oh-my-zsh/issues/449

URL'nin ölmesi durumunda önemli olan kısım:

Komutunuzdaki ^ karakterinden kaçın

Alternatif olarak HEAD ~ 'ı kullanabilirsiniz, böylece her seferinde kaçmak zorunda kalmazsınız.


15
Asla bu komutu hatırlayamıyorum ve bu google ve kendi cevabımı bulmak zorunda hahahaha
Greg Hilston

2
git reset HEAD^benim için zsh çalışıyor, düzeltilmiş olabilir.
Ben Kolya Mansley

@BenKolyaMansley Hangi zsh sürümünü kullanıyorsunuz?
Greg Hilston

Ben kullanıyorumzsh 5.3 (x86_64-apple-darwin18.0)
Ben Kolya Mansley

7

Benim durumumda, repoya zaten ittim. Ah!

Yerel dosyalarınızdaki değişiklikleri koruyarak belirli bir taahhüdü geri alabilirsiniz:

git revert -n <sha>

Bu şekilde ihtiyaç duyduğum değişiklikleri koruyabildim ve zaten itilmiş olan bir taahhüdü çözdüm.


Benim durumumda, uzak depoya zaten ittiğim bir şeyi geri döndürmem gerekiyordu. Daha fazla ah! En iyi yol git revert bad-commit-sha, daha git revert -n revert-commit-just-created-shasonra oradan tamir etmekti . Beni yarıya indirdin. Teşekkürler!
TinkerTenorSoftwareGuy

Bu tam tersini yapıyor gibi görünüyor, değil mi? Seçilen işlemde yapılan değişikliklerin geri alınmasına karşılık gelen yeni değişiklikler yaratır. Bu yeni değişiklikleri yapacak olsaydınız, aslında saklamak istediğiniz işi geri almış olacaksınız.
svaens

3

Git 2.9 (tam olarak 2.9.2.windows.1) git reset HEAD^kullanmak daha fazlasını ister; burada ne girdi olduğundan emin değilim. Lütfen aşağıdaki ekran görüntüsüne bakın

resim açıklamasını buraya girin

git reset HEAD~#numberOfCommitsDeğişikliklerinizi olduğu gibi bırakarak sıfırlamak istediğiniz yerel taahhüt sayısını seçmeyi seçebileceğimiz başka bir çözüm bulundu . Böylece, sınırlı sayıda yerel taahhüdün yanı sıra tüm yerel taahhütleri atma fırsatı elde ederiz.

Aşağıda gösterilen ekran görüntülerine bakın git reset HEAD~1: resim açıklamasını buraya girin

resim açıklamasını buraya girin


Muhtemelen ^ karakterinden kaçmanız gerekiyor - git reset "HEAD ^" veya git reset HEAD \ ^ 'yi deneyin
Mark Fisher

Buna ek olarak, git reset HEAD ^^ tek bir ^ olarak çalışır yeni satır olarak kabul edilir.
John Oss

2

Bunu yapmanın bir yolu daha.

Geçici taahhüdün üzerine taahhüt ekleyin ve ardından şunları yapın:

git rebase -i

İki taahhüdü bir araya getirmek için (komut metin dosyasını açık talimatlarla açar, düzenleyin).


2
Teknik olarak doğru ama hiçbir yere sadece basit kadar zarif git reset HEAD^. Git rebase'in burada hata için çok yeri var.
TheBuzzSaw

0

2020 Basit yol:

git reset <commit_hash>

(Saklamak istediğiniz son taahhüdün taahhüt karması).

Taahhüt zorlanmışsa, şunları yapabilirsiniz:

git push -f

Artık taahhüt edilmemiş değişiklikleri yerel olarak saklayacaksınız

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.