Kayıttaki bir dosyadaki değişiklikleri geri alma


Yanıtlar:


222

Bunu yapmanın en temiz yolu burada anlatılıyor

git show some_commit_sha1 -- some_file.c | git apply -R

VonC'nin yanıtına benzer ancak git showve kullanılıyor git apply.


10
Güzel yapılmış. Komut dosyası çözümü bunun için gereğinden fazla. Neden sadece git revert sha-1 dosya adı olamıyor?
Mark Edington

16
Bu, fatal: unrecognized input
Mac'imde

1
@MerhawiFissehaye: Bence git checkout, commit'de olanı duruma geri döndürmek için değişiklikleri tekrar geri döndürecektir. 'Git add dosya adı yaptım; git commit --amend 'dosyayı commit'den kaldırmak için.
ViFI

3
Sadece bir ipucu, -3yama başarısız olduğunda üç yollu birleştirme için neredeyse her zaman bayrağını git uygulamasına eklemem gerekiyor, çünkü genellikle zamanında bir değişikliği biraz düzeltiyorum.
angularsen

2
Belki çoğu kişi için açıktır, ancak varsa dosyanın yolunusome_file.c içerdiğinden emin olun , aksi takdirde hiçbir şeyi sessizce
yamamazsınız

35

Kaydetme geçmişini değiştirmenin uygun olduğunu varsayarsak, işte önceki bir kaydetmede tek bir dosyadaki değişiklikleri geri almak için bir iş akışı:

Örneğin, badfile.txtkaydetmede 1 dosyadaki ( ) değişiklikleri geri almak istiyorsunuz aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Temel taahhütte yeniden ödeme yapın, sorun taahhüdünü değiştirin ve devam edin.

1) Etkileşimli yeniden tabanı başlatın:

git rebase -i aaa111

2) sorunu işaretleyin değiştirerek editörü düzenlemek için taahhüt picketmek e(düzenlemek için):

e aaa222
pick aaa333

3) Bozuk dosyadaki değişiklikleri geri alın:

git show -- badfile.txt | git apply -R

4) Değişiklikleri ekleyin ve taahhüdü değiştirin:

git add badfile.txt
git commit --amend

5) Rebase'i tamamlayın:

git rebase --continue

Bunun git geçmişini düzenleyebileceğinizi varsaydığını belirtmek isterim. Yukarıdaki bazı yanıtlar, her zaman mümkün / izin verilmeyen, geçmişi düzenlemeden belirli değişikliği tersine çeviren yeni bir kesinleştirme oluşturur.
angularsen

Fantastik. Bu tam olarak aradığım şeydi. Bu fikre zaten sahiptim, ancak etkileşimli yeniden tabanlama yaparken dosyaların editdeğişmiş olarak gösterilmediği konusunda kafam karıştı . Ama git show -- badfile.txt | git apply -Rihtiyacım olan cevabı verdi <3
mraxus

bunu anlarsam, apply -R o dosyadaki commit'i kaldırıp onu orijinal değiştirilmiş durumuna geri döndürür mü?
DaImTo

19

git revert bir kaydetme içindeki tüm dosya içeriği içindir.

Tek bir dosya için komut dosyasını yazabilirsiniz :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

( Smtlaissezfaire'den git-shell-scripts yardımcı programlarından )


Not:

Mevcut değişikliğinizi henüz yapmadıysanız burada başka bir yol açıklanmaktadır .

git checkout -- filename

git checkout bir dosya için bazı seçeneklere sahiptir, dosyayı HEAD'den değiştirerek, değişikliğinizin üzerine yazabilirsiniz.


Dropped.on.Caprica bahseder yorumlarda :

Git'e bir takma ad ekleyebilirsiniz, böylece git revert-file <hash> <file-loc>belirli bir dosyanın geri alınmasını sağlayabilirsiniz . Bu özü
görün .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh

Sadece buradaki tartışmaya eklemek için git'e bir takma ad ekleyebilirsiniz, böylece git revert-file <hash> <file-loc>bu belirli dosyanın geri alınmasını sağlayabilirsiniz . Bu cevabı kaldırdım (doğru çalışması için birkaç düzenleme yapmam gerekse de). .gitconfigDüzenlediğim betiğimin
AlbertEngelB

@ Dropped.on.Caprica iyi bir nokta. Daha fazla görünürlük için cevaba ekledim.
VonC

12

Sadece bu --no-commitseçeneği kullanırdım git-revertve sonra endeksten geri alınmasını istemediğiniz dosyaları nihayet taahhüt etmeden önce kaldırırdım. Aşağıda, en son ikinci işlemede yalnızca foo.c'ye yapılan değişikliklerin nasıl kolayca geri döndürüleceğini gösteren bir örnek verilmiştir:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

İlki git-resettüm dosyaları "aşamaları kaldırır", böylece daha sonra geri alınmasını istediğimiz tek dosyayı geri ekleyebiliriz. Son git-reset --hardkalan dosyadan, saklamak istemediğimiz geri dönüşlerden kurtulur.


9

Çok daha basit:

git reset HEAD^ path/to/file/to/revert

sonra

git commit --amend   

ve sonra

git push -f

dosya gitti ve işlem hash, mesaj vb. aynı.


Tamlık için bir git checkout -- path/to/file/to/revertadıma ihtiyacınız var mı? Ayrıca, hash'in daha sonra aynı olduğu doğru değil, değil mi? Son cümle şu gibi bir şey olarak daha iyi olabilir: "Sonuç, son işlemin, yalnızca geri alınan dosyadaki değişiklikleri içermemesi bakımından farklılık gösteren yeni bir kayıtla değiştirilmesidir."
Kevin

@Kevin muhtemelen haklısın. Bu son satırı iki kez kontrol etmem gerekecek, ancak buna birkaç yıl önce dönüp baktığımda commit hash'in değişmemesi beni şaşırtacak.
Forrest

6
git reset HEAD^ path/to/file/to/revert/in/commit

Yukarıdaki komut dosyayı kesinleştirme dışında alacak, ancak içeriye yansıtacaktır git status.

git checkout path/to/file/to/revert/in/commit

Yukarıdaki komut değişiklikleri geri alır (sonuç olarak HEAD ile aynı dosyayı alırsınız).

git commit

(Taahhüdü --amenddeğiştirmek için geçin.)

git push

Bununla, önceden kaydetmede bulunan dosya kaldırılır ve geri döndürülür.

Yukarıdaki adımlar, commit yapılan şubeden takip edilmelidir.


5

Bu prosedürü takip edebilirsiniz:

  1. git revert -n <*commit*>( -ntüm değişiklikleri geri alın, ancak bunları uygulamayın)
  2. git add <*filename*> (geri döndürmek ve uygulamak istediğiniz dosyaların adı)
  3. git commit -m 'reverted message' (geri almak için bir mesaj ekleyin)
  4. taahhüt ettikten sonra diğer dosya değişikliklerini atın, böylece dosyalar geri dönmeden önce yaptığınız değişikliklerle güncel kalır

1

Bir dosyadaki değişiklikleri son kaydetmenizden sıfırlamak isterseniz, genellikle kullandığım şey budur. Bunun en basit çözüm olduğunu düşünüyorum.

Lütfen dosyanın hazırlık alanına ekleneceğini unutmayın.

git checkout <prev_commit_hash> -- <path_to_your_file>

Umarım yardımcı olur :)

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.