Git ile bir taahhüdün bir kısmını geri alma


144

Git'te belirli bir taahhüdü geri almak istiyorum. Ne yazık ki, kuruluşumuz hala CVS'yi standart olarak kullanıyor, bu yüzden CVS'ye geri döndüğümde çoklu git taahhütleri bir araya getiriliyor. Bu durumda orijinal git taahhüdünü ayırmak isterim, ama bu imkansız.

Buna benzer bir yaklaşım git add --patch, bir taahhüdün hangi bölümlerinin geri döndürüleceğine karar vermek için farkları seçerek düzenlememe izin verecek mi?


Burada daha fazla çözüm var , ancak belirli dosyalarla kısmi geri dönüşü sınırlamaya odaklanıyor.
ntc2

Yanıtlar:


226

Değişiklikleri kaldırmak için --no-commit( -n) seçeneğini kullanın git revert, ardından şunu kullanın git add --patch:

$ git revert -n $bad_commit    # Revert the commit, but don't commit the changes
$ git reset HEAD .             # Unstage the changes
$ git add --patch .            # Add whatever changes you want
$ git commit                   # Commit those changes

Not: git add --patch kullanarak eklediğiniz dosyalar saklamak istediğiniz dosya değil, geri almak istediğiniz dosyalardır.


13
Git'e çok aşina olmayanlar için gerekli son komutu eklemeye değer olabilir: taahhütte bulunduktan sonra, git reset --hardgeri almak istemediğiniz diğer değişiklikleri atmak.
tremby

15
git reset --hardaranan düzenlemeleri kaybedebileceği için yeni başlayanlar için tehlikelidir. Bunun yerine alışmak git status, git checkout -- FILE..şeyleri daha güvenli bir şekilde geri döndürmek için ipuçları verir .
Tino

Ne kadar şaşkın bir ihmal git; git revertsadece bir --patchargüman almalı .
Kaz

@Kaz: git reverttüm taahhütleri geri almak için kullanılır. git checkout -pGeri döndürülecek bitleri etkileşimli olarak seçmek için kullanabilirsiniz .
mipadi

1
Ayrıca (belki de) bariz olanı eklemek istiyorum, ki bu ilk önce çalışmanızı kaydedin . Ya commitilk ya stash, o zaman deneyin revert.
Felipe Alvarez

39

Aşağıdakileri başarıyla kullandım.

İlk önce tam taahhüdü geri döndürün (dizine koyar) ama taahhüt etmeyin.

git revert -n <sha1>  # -n is short for --no-commit

Ardından, geri döndürülen İYİ değişiklikleri dizinden etkileşimli olarak kaldırın

git reset -p          # -p is short for --patch  

Sonra kötü değişikliklerin tersini yapın

git commit -m "Partially revert <sha1>..."

Son olarak, geri döndürülen İYİ değişiklikleri (reset komutuyla değiştirilmemiş olan) hala çalışma ağacındadır. Temizlenmesi gerekiyor. Çalışma ağacında başka taahhüt edilmemiş değişiklik kalmazsa,

git reset --hard

5
Bu, kabul edilen cevaba (kullanan reset HEAD .) üstün bir alternatif değil mi , çünkü çalışma direktörünün son temizlenmesini gerektirmiyor mu?
Steven Lu

2
Bu cevap üstündür, çünkü onu takip reset -petmekten daha kısadır . Ancak sıfırlanmış olan "iyi" iri parçalar, taahhütten sonra hala çalışma dizininde olduğundan, temizleme işlemini yine de gerektirir. reset HEADadd -p
Chiel ten Brinke

Bu yanıt üstün değildir, çünkü istediğiniz değişiklikleri etkileşimli olarak kaldırmak genellikle kafa karıştırıcı ve hataya açıktır - özellikle herhangi bir düzenleme gerekiyorsa.
Kaz

5

Şahsen, otomatik olarak oluşturulan taahhüt mesajını yeniden kullanan ve kullanıcıya son olarak işlemeden önce "Kısmen" kelimesini düzenleme ve yapıştırma fırsatı veren bu sürümü tercih ederim.

# generate a revert commit
# note the hash printed to console on success
git revert --no-edit <hash to revert>

# undo that commit, but not its changes to the working tree
# (reset index to commit-before-last; that is, one graph entry up from HEAD)
git reset HEAD~1

# interactively add reversions
git add -p

# commit with pre-filled message
git commit -c <hash from revert commit, printed to console after first command>

# reset the rest of the current directory's working tree to match git
# this will reapply the excluded parts of the reversion to the working tree
# you may need to change the paths to be checked out
# be careful not to accidentally overwrite unsaved work
git checkout -- .

4

Çözüm:

git revert --no-commit <commit hash>
git reset -p        # every time choose 'y' if you want keep the change, otherwise choose 'n'
git commit -m "Revert ..."
git checkout -- .   # Don't forget to use it.

Kabul edilen çözümden nasıl farklı olduğunu söylerseniz insanlara yardımcı olur
CharlesB

1
@Krzysztof Sondaki ödeme neden önemlidir ve bu çözüm neden user1338062 'den farklıdır?
martin

3

Başka bir alternatif (bir dosyanın geçerli sürümünüz geri döndürmeye çalıştığınız sürümden çok uzak değilse), kısmen geri almak istediğiniz dosyadan hemen önce taahhüdün karmasını elde etmektir git log. Sonra komutunuz:

$ git checkout -p <hash_preceding_commit_to_revert> -- file/you/want/to/fix.ext

Bu, çalışma ağacınızdaki dosyaları değiştirir, ancak hiçbir taahhüt oluşturmaz, bu yüzden gerçekten doldurursanız tekrar başlayabilirsiniz git reset --hard -- file/you/want/to/fix.ext.


1

Git-revert -n komutunu kullanabilir ve sonra öbekleri seçmek için add --patch komutunu kullanabilirsiniz.

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.