GIT'de kısmi bir geri dönüş yapabilir miyim


156

Çoklu dosya taahhüdünde yalnızca tek bir dosyayı veya bir dosyadaki belirli değişiklikleri geri almak mümkün müdür?

Tüm hikaye bir sürü dosya işledim. Daha sonra, isimsiz kalacak birisinin (JACK !!!) birisini deposuna kopyaladı ve yaptığım bazı değişikliklerin üzerine yazarak birkaç dosya işledi. Daha iyi ya da daha iyi olan bir dosyayı geri almak istiyorum, içeri girip o dosyadaki iki değişikliği geri almak istiyorum. Çekildiği ve itildiği için bunun ayrı bir geri dönüş taahhüdü olması gerekecektir.


Brian beni doğru yola soktu. Git add --patch kullanarak ve sonra istediğim şeyi almak için yama içinde düzenleme işlevini kullanarak sona erdi.
Debriyaj

2
Oyuna oldukça geç kaldım ama bence "doğru" cevabı buldum .
ntc2

@ ntc2 Garip bir şekilde, kabul edilen cevap benim için bağladığınız cevaptan çok daha iyi çalıştı - yamaları uygulamakta başarısız olmak yerine çözmek için birleştirme çatışmaları yarattı.
Iiridayn

@liridayn Bütün cevabımı okudun mu? "Varyasyonlar" bölümünde --3way, yamaların uygulanamaması yerine birleştirme çakışmalarına sonuç eklenmesinin talep edildiğini iddia ediyorum .
ntc2

Yanıtlar:


204

'--No-commit' seçeneğini ekleyerek yeni bir tane oluşturmadan taahhüdü geri alabilirsiniz. Bu, geri döndürülen tüm dosyaları hazırlama alanında bırakır. Oradan yumuşak bir sıfırlama yapardım ve gerçekten istediğim değişiklikleri eklerdim. Örnek bir iş akışı için:

git revert <sha-of-bad-commit> --no-commit
git reset   // This gets them out of the staging area
<edit bad file to look like it should, if necessary>
git add <bad-file>
git checkout . // This wipes all the undesired reverts still hanging around in the working copy
git commit

42
Yazılım sıfırlamasından sonra, git add -ptüm dosyalar yerine seçici olarak dosya parçaları eklemenizi sağlayan etkileşimli bir oturum başlatmak için de yapabilirsiniz . ( git reset -pSeçici olarak değişmeyen değişiklikler de var. Bilmek güzel, ama muhtemelen bu senaryoda ne istediğinizi değil.)
Stéphan Kochen

1
Tam da aradığım şey buydu: Çalışma kopyasına geri dönün, etkileşimli olarak yakışıklı seçin, taahhüt edin. Bunun için büyük, tuzlu bir adam
smooch

Bu bir ilham Başka bir çözüm olacaktır revert, reset, stash -p, (zulası "Ben aslında marka istemiyorum o iptal") add, dinlenmecommit
Cyril CHAPON

82

checkoutKomutu kullanarak bir dosyanın eski sürümünü etkileşimli olarak uygulayabilirsiniz .

Örneğin, COMMITgeri eklenecek kodun nerede kaldırıldığını biliyorsanız, aşağıdaki komutu çalıştırabilirsiniz:

git checkout -p COMMIT^ -- FILE_TO_REVERT

Git, dosyanın geçerli sürümünde eksik olan parçaları geri eklemenizi ister. eDeğişikliği geri uygulamadan önce bir düzeltme eki oluşturmak için kullanabilirsiniz .


Yalnızca dosyanın bir kısmını geri almak istiyorsanız çok kullanışlıdır! Temel olarak, kafadan parçalar almak için,git checkout -p path/to/file
falstaff

40

Geri almak istediğiniz dosyaların eski, iyi içeriklerini manuel olarak kontrol edebilirsiniz git checkout. Örneğin my-important-file, sürümde olduğu sürüme geri dönmek abc123isterseniz,

git checkout abc123 -- my-important-file

Artık my-important-filearkadaki eski içeriğe sahipsiniz ve hatta isterseniz bunları düzenleyebilir ve yaptığı değişiklikleri geri alacak bir taahhütte bulunmak için her zamanki gibi taahhütte bulunabilirsiniz. Taahhüdünün geri dönmek istediğiniz sadece bazı bölümleri varsa, taahhüt ettiğiniz git add -pyamadan sadece birkaç parça seçmek için kullanın .


19
Bu bir değil revert, sadece dosyanın eski bir sürümünü geri alıyorsunuz. Uygun revertolan, dosyadaki kötü işlem değişikliklerini, bu kötü işlemden beri birkaç kez değiştirilmiş olsa bile kaldırır ve bu değişiklikleri kaybetmek istemezsiniz .
Mart'ta Totor

2
Totor, cevabımı gör. Değişiklikleri kaydetmek için '-p' kullanabilirsiniz. Cevap aslında buna çok yakın.
cmcginty

1
Ya da bunu birleştirebilirsiniz git checkout -p.
Léo Lam

31

Git posta listesinde bunu yapmanın bir yolunu buldum:

git show <commit> -- <path> | git apply --reverse

Kaynak: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html#a6064406

Varyasyonlar

Yama temiz bir şekilde uygulanmazsa, bu komut başarısız olur (ancak değişikliklere neden olmaz), ancak --3waybunun yerine sizinle daha sonra elle çözebileceğiniz çakışmalar alır (bu durumda Casey'nin cevabı daha pratik olabilir):

git show <commit> -- <path> | git apply --reverse --3way

Bunu, birden fazla işlemi kısmen geri almak için de kullanabilirsiniz, örneğin:

git log -S<string> --patch | git apply --reverse

<string>herhangi bir taahhütte eşleşen değişikliklerle dosyaları geri almak için. Bu tam olarak benim kullanım durumumda ihtiyaç duyduğum şeydi (birkaç ayrı taahhüt, farklı dosyalara benzer değişiklikler getirdi, diğer dosyaları da geri döndürmek istemediğim ilgisiz yollarla değiştirdi).

Eğer diff.noprefix=trueayarladıysanız , komuta ~/.gitconfigeklemeniz gerekir , örn.-p0git apply

git show <commit> -- <path> | git apply -p0 --reverse

Bu yanıt kabul edilen yanıttan çok daha iyidir: "daha iyisi, içeri girin ve o dosyadaki iki değişikliği geri alın".
yeniden yazıldı

Bir taahhüdün sadece bir kısmını geri almak istedim, bu yüzden yaptım: (1) git show ... > foo.txt (2) hala listelenmemiş diffs geri dönmek için (3)foo.txt geri dönmek istemediğim diffs kaldırmak için düzenleyin . git apply --reverse foo.txtfoo.txt
cxw

Git show bölümüne --binary --full-index eklemek de yararlı bir varyasyon olabilir
Laurynas Biveinis
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.