Git'teki gönderilmemiş değişikliklerin bir kısmını geri alma


158

Git'teki kaydedilmemiş değişikliklerimin bazı bölümlerini nasıl geri alabilirim, ancak geri kalanını etiketsiz olarak nasıl saklayabilirim? Çözdüğüm yol:

git commit --interactive
# Choose the parts I want to delete
# Commit the changes
git stash
git rebase -i master # (I am an ancestor of master)
# Delete the line of the most recent commit
git stash apply

Bu işe yarar, ancak git commit --interactiveyalnızca değişiklikleri geri almak için bir şey olsaydı iyi olurdu . Daha iyi yöntemler var mı?

Yanıtlar:


265

git checkout -pGeri döndürmek için çalışma kopyanız ile dizininiz arasındaki farktan tek tek parçalar seçmenize olanak tanıyan kullanabilirsiniz . Aynı şekilde, git add -pdizine eklenecek iri parçalar seçmenize git reset -pizin verir ve dizin ile HEAD arasındaki farktan dizinden çıkmak için ayrı ayrı öbekler seçmenize olanak tanır.

$ git checkout -p file/to/partially/revert
# or ...
$ git checkout -p .

Git deponuzu bu değişiklikleri geri almadan önce korumak için önceden anlık olarak çekmek istiyorsanız, şunu yapmayı seviyorum:

$ git stash; git stash apply

Bunu sık kullanırsanız, takma ad vermek isteyebilirsiniz:

[alias]
    checkpoint = !git stash; git stash apply

İyi bir editör modu veya eklenti -pkullanırsanız, bazen kullanmak için biraz beceriksiz olabileceğinden , doğrudan geri döndürülecek satırları seçmek için destek sağlayabilecek tek tek iri parçaların veya satırların geri döndürülmesi daha da kolay olabilir . Git ile çalışmak için çok yararlı olan Emacs modu Magit kullanıyorum . Magit'te, magit-statusgeri almak istediğiniz değişikliklerin farklarını bulabilir, geri almak istediğiniz satırları seçebilir (veya imleci tek seferde bir iri geri almak istiyorsanız geri almak istediğiniz imlecin üzerine getirebilirsiniz. aynı anda bir satır) seçin ve kbu belirli satırları geri almak için tuşuna basın . Emacs kullanıyorsanız Magit'i tavsiye ederim.


Sanırım bu, başlangıçta bulduğum çözüm kadar karmaşık, ancak orijinal çözümümün, kaldırılan çizgileri 30 gün boyunca kaydetme avantajına sahip olduklarını düşünüyorum çünkü taahhütte bulundular. Ben belki etrafında yazılmış bir kabuk komut dosyası olması güzel olurdu düşünüyorum.
asmeurer

1
Maalesef, sadece tek bir komutla tam olarak ne istediğini yapan git checkoutbir -pbayrağı olduğunu fark ettim . Önceki karmaşık adımlar dizisi için özür dileriz; sadece kullanabilirsiniz git checkout -p. Bir şeyleri kurtarmaya gelince, potansiyel olarak yıkıcı bir şey yapmadan önce , mevcut ağacı saklamak için sık sık bir şey git stash; git stash apply(veya bunu yapan bir takma ad oluşturuyorum git checkpoint), böylece bir şeyler ters giderse geri dönebilirim.
Brian Campbell

İşte böyle, çözüm bu! Takma ad olarak, git commit -a -m "Backup Commit" --edit; git reset HEAD^ daha iyi bir şey olacağını düşünüyorum , çünkü o zaman başka bir şey için kullanıyor olabileceğim saklı durumumu kirletmezdi. Daha sonra, SHA1'e sahip olduğunuz sürece, önümüzdeki 30 gün içinde kiraz toplayabilirsiniz. --Edit, daha sonra isterseniz SHA1'i bulmanıza yardımcı olmak için işlem mesajına bilgi eklemenizi sağlar. Öte yandan, bu git reflog kirletir, bu yüzden ne yaptığınıza dayalı bir tradeoff sanırım.
asmeurer

Denetim noktası diğer adı benim için çalışmıyor: yalnızca ilk komut yürütülür, ikincisi değil. Bu üzücü, çünkü çok isterdim. Git 1.7.10.4 sürümünü kullanıyorum.
Fabien

git checkout -pYamaları dizine uygulamak değil, yalnızca sahneye koymak için bir yol var mı ?
Geremia

28
git diff > patchfile

Ardından yama dosyasını düzenleyin ve geri almak istemediğiniz parçaları kaldırın, ardından:

patch -R < patchfile

6
Bununla birlikte, bu cevap özellikle basitliği ve kullanım kolaylığı açısından takdire şayan. +1
tholy

Oluşturulan patchfilevim harika görünüyor ve gerçekten yardımcı oluyor!
Bily

Mükemmel. Windows için Cygwin ve Windows için Ubuntu bash ile de çalıştığını onaylayabilir.
Checo R

1
Ayrıca kullanabilirsiniz Not git apply -Ryerine patch(git alemlerine içinde sadece kalmak, ya da aksine olay patchmevcut değildir)
user1556435

patch: **** malformed patch at line 41: @@ -428,9 +443,9 @@ you should place your code here."
HappyFace

5

Yapabilirsin

git checkout master -- path/to/file

Sıfırlamak istediğiniz her dosya için.


Veya bir dal üzerinde çalışıyorsa master yerine HEAD kullanın. 'Git durumu' raporunda belirtildiği gibi (en azından son sürümlerde).
Jonathan Leffler

1

Peki ya

  1. Etkilenen dosyaları dizindeki değişikliklerle geri alma
  2. git add -pyalnızca dizine eklemek istediğiniz değişiklikleri geri eklemek için kullanın .

1

'Git status' komutunu çalıştırdığımda şöyle yazıyor:

$ git status
# On branch fr/fr.002
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   makefile
#
no changes added to commit (use "git add" and/or "git commit -a")
$

Bu nedenle, düzenlenmemiş düzenlemeleri iptal etmek için çalıştırmamı söylüyor:

git checkout -- makefile

3
Sanırım bir kerede tüm bir dosyayı değil, tek tek parçaların nasıl geri alınacağını merak ediyordu. Tabii ki, bir dosyadaki tüm değişiklikleri geri almanız gerekiyorsa çözüm budur.
Brian Campbell

Evet, sanırım haklısın. Söylediğiniz gibi 'git checkout -p' ve 'git add -p' seçeneklerinin istendiği gibi görünmesi olasıdır.
Jonathan Leffler

1

Brian Campbell'ın cevabı , gitmem, sürüm 1.9.2.msysgit.0'ımı bilinmeyen nedenlerden dolayı çöküyor, bu yüzden yaklaşımım tutmak istediğim iri parçalara sahne olmak, çalışma kopyasındaki değişiklikleri atmak, sonra da bozulmak.

$ git add -p
   ... select the hunks to keep
$ git checkout -- .
$ git reset HEAD .

1
Ayrıca var git stash -p. Yapabilirsin git stash -p; git reset --hard; git stash pop. Bu, kesin bir mesaj yazmak zorunda kalmamanız dışında, yaptığınızla aynıdır.
asmeurer

@asmeurer alkış. Benimki bir taahhüt mesajı gerektirmez, ancak stash'ı kullanmak için endeksten daha mantıklıdır.
G-Wiz

0

Yapabileceğiniz git checkoutve bunu geri almak istiyor parçaların da isim vermek.

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.