Git: Herhangi bir depodaki dosyaları silmeden dosya dizinden nasıl kaldırılır


163

Kullandığınızda

git rm --cached myfile

hedef yerel dosya sisteminden silinmez. Ancak dosyayı zaten sürümlendirip taahhüt ettiyseniz, merkezi bir depoya ittiyseniz ve komutu kullanmadan önce başka bir depoya çektiyseniz, dosyayı bu sistemden siler.

Herhangi bir dosya sisteminden silmeden dosyayı sürümden kaldırmanın bir yolu var mı?

Düzenleme: Açık, umarım.


Belki de kullanım durumunuzu genişletebilirsiniz. Dizin, bir sonraki işlem için hazırlama alanıdır, bu nedenle dosyayı geçerli daldan kaldırmak istemiyorsanız neden dizinden kaldırmak istersiniz?
CB Bailey

1
Üzgünüm. Dosyamın nedense uzun zaman önce yerine getirildiğini ve dağıtıldığını söylemek istedim. Şimdi amaç, insanların sistemlerinden silmeden sürümden kaldırmaktır. Bunun ortaya çıkmasının nedeni, yanlışlıkla bir yapılandırma dosyasını sürümlendirmemdir. Yapılandırma dosyası gereklidir, bu yüzden yabancı sistemlerden kaldırmak istemiyorum.
Fletcher Moore

Soruyu daha açık olacak şekilde düzenledim.
Fletcher Moore

3
git rm --cached, dosyayı diğer çalışma dizininden kaldırmaz. Dosya yalnızca bu dizinde çalışan biri bir çekme işlemi gerçekleştirirse kaldırılır. Dosya, "git checkout HEAD @ {1} foo" ile kolayca kurtarılabilir (çekildikten hemen sonra yürütülürse)
William Pursell

Yanıtlar:


119

Git taahhüdünün “bu dosyayı izlemeyi durdurun, ancak silmeyin” gibi bir niyet kaydedebileceğini sanmıyorum.

Böyle bir niyetin yürürlüğe girmesi, dosyayı silen bir taahhüdü birleştiren (veya yeniden adlandırılan) depolarda Git dışında müdahale gerektirir.


Bir Kopyasını Kaydet, Silme Uygula, Geri Yükle

Muhtemelen yapılacak en kolay şey, alt kullanıcılarınıza dosyanın bir kopyasını kaydetmelerini, silmenizi çekmelerini ve ardından dosyayı geri yüklemelerini söylemektir. Rebase aracılığıyla çekiyorlar ve dosyada değişiklikler yapıyorlarsa, çakışmalar yaşayacaklar. Bu tür çakışmaları gidermek için, git rm foo.conf && git rebase --continue(çakışan işlem kaldırılan dosyadakilerin dışında değişiklikler git rebase --skipvarsa ) veya (çakışan işlem yalnızca kaldırılan dosyaya değiştiyse) kullanın.

Silinen bir İşlem Yaptıktan Sonra Dosyayı İzlenmemiş Olarak Geri Yükle

Silme taahhüdünüzü zaten çekmişlerse, yine de git show ile dosyanın önceki sürümünü kurtarabilirler :

git show @{1}:foo.conf >foo.conf

Veya git checkout ile (William Pursell tarafından yapılan yorum başına; ancak dizinden yeniden kaldırmayı unutmayın!):

git checkout @{1} -- foo.conf && git rm --cached foo.conf

Silme işleminizi çektikten sonra başka eylemlerde bulunduysa (veya rebase ile ayrı bir HEAD'a çekiyorlarsa), başka bir şeye ihtiyaçları olabilir @{1}. git log -gSilmenizi çekmeden hemen önce taahhüdü bulmak için kullanabilirler .


Bir yorumda, “izlemek, ancak saklamak” istediğiniz dosyanın, yazılımı çalıştırmak için gereken bir tür yapılandırma dosyası olduğunu (doğrudan depodan) belirttiğinizden bahsediyorsunuz.

Dosyayı 'Varsayılan' Tutun ve Manuel / Otomatik Olarak Etkinleştirin

O depoda Yapılandırma dosyasının içeriğini korumak için devam etmek tamamen kabul edilemez değilse, siz (örn) den izlenen dosyayı yeniden adlandırmak mümkün olabilir foo.confiçin foo.conf.defaultve sonra kullanıcılar talimat için cp foo.conf.default foo.confyeniden adlandırma taahhüt uygulandıktan sonra. Kullanıcılar Makefile, yazılımınızı başlatmak / dağıtmak için deponun varolan bir kısmını (örn. Havuzdaki içerik tarafından yapılandırılmış (örn. Veya benzeri)) mevcut bir bölümünü zaten kullanıyorsa , başlatma / konuşlandırma süreci:

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf

Yerinde böyle bir varsaymak mekanizma ile kullanıcılar bir o yeniden adlandırır işlemek çekin gerekir foo.confiçin foo.conf.defaultilave bir çaba harcamanıza gerek kalmadan. Ayrıca, gelecekte ek kurulumlar / depolar yaparsanız, bir yapılandırma dosyasını el ile kopyalamak zorunda kalmazsınız.

Geçmişi Yeniden Yazmak Yine de Manuel Müdahale Gerektirir…

İçeriğin depoda tutulması kabul edilemezse, büyük olasılıkla içeriği geçmişten tamamen silmek istersiniz git filter-branch --index-filter …. Bu, her şube / depo için manuel müdahale gerektiren yeniden yazma geçmişine denk gelir ( git rebase kılavuzundaki “Yukarı Akış Rebase'den Kurtarma” bölümüne bakın ). Yapılandırma dosyanız için gereken özel işlem, yeniden yazma işleminden kurtarırken gerçekleştirmeniz gereken başka bir adım olacaktır:

  1. Yapılandırma dosyasının bir kopyasını kaydedin.
  2. Yeniden yazma işleminden kurtarın.
  3. Yapılandırma dosyasını geri yükleyin.

Nüksü Önlemek için Yoksay

Hangi yöntemi kullanırsanız kullanın, büyük olasılıkla .gitignorehavuzdaki bir dosyaya yapılandırma dosya adını dahil etmek isteyeceksiniz, böylece hiç kimse yanlışlıkla istemeyecektir git add foo.conf(bu mümkündür, ancak -f/ gerektirir --force). Birden fazla yapılandırma dosyanız varsa, hepsini tek bir dizine 'taşımayı' ve her şeyi görmezden gelmeyi düşünebilirsiniz ('taşıyarak' Programın yapılandırma dosyalarını bulmayı beklediği yeri değiştirmek ve kullanıcıları almak (veya başlatma / dağıtma mekanizması) dosyaları yeni konumlarına kopyalamak / taşımak için; açık bir şekilde görmezden geleceğiniz bir dizine mv gitmesini istemezsiniz ).


5
İnanılmaz derecede kapsamlı yanıt. Teşekkür ederim!
Fletcher Moore

Tom Power'ın cevabı aşağıda ilk cümlenizle çelişiyor gibi görünüyor.
Mike S

1
@MikeS: Etkisi --{,no-}assume-unchangedtamamen yereldir: durumu doğrudan taahhütlere kaydedilmez. Bir deponun dosyada yeni değişiklikler yapmasını önlemeye yardımcı olabilir, ancak sürüm denetiminden kaldırmaz. İlgili, ilgili, çıplak olmayan tüm depolarınız için ayarlayabilirseniz, durumunuza yardımcı olabilir, ancak bu, doğrudan ilgili + çıplak / olmayan diğer depolara (özellikle de asıl sorucının soruyla ilgili açıklayıcı açıklamalarına göre şunları kontrol etmezsiniz: “insanların sistemleri” / “yabancı sistemler” bölümüne bakınız).
Chris Johnsen

1
I do not think a Git commit can record an intention like “stop tracking this file, but do not delete it”.- şimdi yapabilir, ilegit rm --cached foo.conf
Nick Volynkin

1
@NickVolynkin: Soru zaten bunun sorucunun amacı için yetersiz olduğunu göstermiyor mu? (Sonuçtaki taahhüt başka bir depoya çekildiğinde dosyayı otomatik olarak tutmak?
Chris Johnsen

86

Bu sorun yanlışlıkla işlediğimde aynı hafta vardı, daha sonra bir paylaşılan dosyayı bir depodan kaldırmaya çalıştım ve bu:

http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

benim için iyi çalıştı ve şu ana kadar bahsedilmedi.

git update-index --assume-unchanged <file>

İlgilendiğiniz dosyayı sürüm denetiminden kaldırmak için, diğer tüm komutlarınızı normal şekilde kullanın.

git update-index --no-assume-unchanged <file>

Eğer geri koymak isteseydin.

Düzenleme: Lütfen Chris Johnsen ve KPM'nin yorumlarına bakın, bu sadece yerel olarak çalışır ve eğer yapmazlarsa dosya diğer kullanıcılar için sürüm kontrolü altında kalır. Kabul edilen cevap, bununla başa çıkmak için daha eksiksiz / doğru yöntemler verir. Ayrıca bu yöntemi kullanıyorsanız bağlantıdan bazı notlar:

Açıkçası bu konuda devreye giren birkaç uyarı var. Dosyayı doğrudan eklerseniz git, dizine eklenir. Bu bayrakla bir taahhüdün birleştirilmesi, birleştirmenin zarif bir şekilde başarısız olmasına neden olarak manuel olarak işleyebilmenize neden olur.


7
Bu, belirtilen özel sorunun cevabı değildir. Yalnızca kendi yerel deponuz için çalışacaktır, bu nedenle her kullanıcı bunu kendisi yapmak zorundadır. Bu bir acı.
KPM

28

Dosyayı dizinden kaldırmak için şunu kullanın:

git reset myfile

Bu, yerel kopyanızı veya başka birinin kopyasını etkilememelidir.


1
resetyalnızca dosya geçerli HEAD işleminde değilse dosyayı dizinden kaldırır, aksi takdirde dizin sürümünü geçerli HEAD sürümüne geri döndürür.
CB Bailey

1
Belki de soruyu yanlış anladım, ancak herhangi bir taahhüdü etkilemeden bir dosyayı dizinden kaldırmakla ilgili gibi görünüyor.
Armand

Charles'ın dediği gibi, sıfırlama "bir dosyayı kaldırmaz". Daha fazla bilgi için git help reset yazın.
Simon B.

4
Bu, "Herhangi bir depodaki dosyaları silmeden dosya dizinden nasıl kaldırılır" başlıklı soruyu yanıtlar. OP gerçekten "Yerel kopyayı silmeden bir dosyayı nasıl kaldırırım" sorusunu soruyordu.
hewsonism

@hewsonism OP "herhangi bir dosya sistemi" (herhangi bir düzenlemeden önce bile) dedi.
jbobbins


15

git rm --cachedKomutu yaptıktan sonra myfile, .gitignoredosyaya eklemeyi deneyin (yoksa oluşturun). Bu git'e yoksaymasını söylemelidir myfile.

.gitignoreBunu taahhüt ve uzak deposuna itin gerekir, yani dosyanın sürüm edilir.


1

Benim çözüm diğer çalışma kopyasını çekmek ve sonra yapmaktır:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

en son yorumda tüm dosya yollarını alın ve bunları HEAD'in üst öğesinden kontrol edin. İş bitmiş.


0

Yukarıdaki çözümler çoğu durumda işe yarar. Bununla birlikte, o dosyanın tüm izlerini de kaldırmanız gerekirse (ör. Şifreler gibi hassas veriler), dosya yine de alınabileceğinden dosyayı tüm yürütme geçmişinizden kaldırmak istersiniz.

İşte dosyanın tüm izlerini tüm varoluş geçmişinizden kaldıran, sanki hiç varmamış gibi, ancak dosyayı sisteminizde yerinde tutan bir çözümdür.

https://help.github.com/articles/remove-sensitive-data/

Yerel git deponuzdaysanız ve kuru çalışma yapmanız gerekmiyorsa 3. adıma atlayabilirsiniz. Benim durumumda, .gitignore dosyamı önceden oluşturduğum ve üzerinde çalışmak istediğim depodayken yalnızca 3. ve 6. adımlara ihtiyacım vardı.

Değişikliklerinizi görmek için deponuzun GitHub köküne gitmeniz ve sayfayı yenilemeniz gerekebilir. Ardından, bir kez dosyaya sahip olan eski bir taahhüde ulaşmak için, şimdi kaldırıldığını görmek için bağlantılar arasında gezinin. Benim için, sadece eski taahhüt sayfasını yenilemek değişikliği göstermedi.

İlk başta korkutucu görünüyordu, ama gerçekten kolay ve bir cazibe gibi çalıştı! :-)

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.