Git ile dosya kopyalama işlemini kaydetme


141

Git'te bir dosyayı git-mv kullanarak taşıdığımda durum dosyanın yeniden adlandırıldığını gösterir ve bazı bölümleri değiştirsem bile yine de aynı şey olduğunu düşünür (ki bu iyi çünkü geçmişini takip etmeme izin veriyor) .

Bir dosyayı kopyaladığımda, orijinal dosyanın bazı geçmişleri var, yeni kopyayla ilişkilendirmek istiyorum.

Dosyayı hareket ettirmeyi denedim ve sonra orijinal konumunda yeniden ödeme yapmaya çalıştım - bir kez taşındığında git orijinal konumu kontrol etmeme izin vermiyor.

Bir dosya sistemi kopyası yapmayı ve sonra dosyayı eklemeyi denedim - git yeni bir dosya olarak listeler.

Git kaydını bir dosya kopyalama işlemine, geçmişin orijinal dosyaya kadar izlenebileceği bir dosya yeniden adlandırma / taşıma kaydına benzer şekilde yapmanın bir yolu var mı?

Yanıtlar:


112

Git, yeniden adlandırma izlemeyi veya kopya izlemeyi yapmaz, yani yeniden adlandırma veya kopya kaydetmez . Bunun yerine, yeniden adlandırma ve kopyalama algılama . Sen yeniden adlandırma tespit edilmekten talep edebilir git diff(ve git showkullanarak) -Mseçeneğini kullanarak değiştirilebilir dosyalarda ek kopya algılama talep edebilir -Cseçeneği ( -Cima -M) ve tüm dosyalar arasında daha pahalı kopya algılama isteyebilir --find-copies-harderveya -C -Cima ( -Canlamına gelen -M). Bkz git-diff manpage.

Git'i her zaman diff.renamesbir boolean true değerine (ör. trueVeya 1) ayarlayarak yeniden adlandırma algılaması yapacak şekilde yapılandırabilir ve git'i de copyveya olarak ayarlayarak kopya algılamasını yapmasını isteyebilirsiniz copies. Bkz git-config manpage.

Ayrıca kontrol -lseçeneği git diffve ilgili yapılandırma değişkeni diff.renameLimit.


git log <pathspec>Git'te farklı şekilde çalıştığına dikkat edin: burada <pathspec>yolun (alt) bir dizin adı olabileceği yol sınırlayıcıları kümesi. Yeniden adlandırma ve kopya algılama devreye girmeden önce geçmişi filtreler ve basitleştirir . Yeniden adlandırmaları ve kopyaları takip etmek istiyorsanız, git log --follow <filename>(şu anda biraz sınırlı olan ve yalnızca tek dosya için çalışan) kullanın.


1
@allyourcode: Ne hakkında kafanız karıştı? Kopya algılamayı varsayılan olarak açmak diff.renamesiçin copies(örn. ' git config diff.renames copies') Ayarını yapın . Ben biraz mantıksız olduğunu kabul ediyorum.
Jakub Narębski

Ayrıştıramadığım bir bölüm "ve varsayılan olarak algılamayı yeniden adlandırmayı da isteyebilirsiniz". Diff.renames'in kullanabileceği dört değer olduğunu mu söylüyorsunuz (true, 1, copy, copys) ve hepsinin aynı şeyi yaptıklarını mı söylüyorsunuz?
allyourcode

1
@allyourcode: Üzgünüm, bunu fark etmedim. Şimdi düzeltildi, teşekkürler.
Jakub Narębski

4
@ peschü: Git, depo olarak içerik adresli nesne veritabanını kullanır. Dosya içerikleri, SHA-1 içerik karması olan adres altında 'blob' içeriklerinde saklanır (iyi, + uzunluk + içerik yazın). Bu, verilen içeriğin yalnızca bir kez depolandığı anlamına gelir. Nb. bu otomatik veri tekilleştirme, git paketi biçimini kullanarak "bup" yedekleme sistemi oluşturmanın arkasındaki nedendi.
Jakub Narębski

1
Aşağıdaki çözümün aksine, bu bir aralıktaki değişiklik izleme ile çalışmaz. Git günlüğü, git log -L123,456:file.xyzyeniden adlandırmaları doğru bir şekilde izleyen ancak kopyaları izlemeyen bir aralık bağımsız değişkenine ( ) izin verir ve bu durumda --follow; Ayrıca, AFAICT, bu git suçlama ile çalışmaz.
Clément

57

2020-05-19: Aşağıdaki çözüm, orijinal dosyanın günlüğünü değiştirmeme, bir birleştirme çakışması oluşturmama ve daha kısa olma avantajlarına sahiptir.

Git'i kopyalanan dosyanın geçmişini üç işlemde algılamaya zorlayabilirsiniz:

  • Kopyalamak yerine, yeni bir şubeye geçin ve dosyayı orada yeni konumuna taşıyın .
  • Orijinal dosyayı buraya tekrar ekleyin.
  • Hızlı ileri sarma seçeneği ile yeni dalı orijinal dalıyla birleştirin --no-ff.

(Krediler Raymond Chen'e gider .)


Eski çözümün dört taahhüdü vardı:

  • Kopyalamak yerine, yeni bir şubeye geçin ve dosyayı orada yeni konumuna taşıyın .
  • Özgün şubeye geçin ve dosyayı yeniden adlandırın.
  • Her iki dosyayı tutarak önemsiz çakışmayı gidererek yeni dalı orijinal dalıyla birleştirin.
  • Özgün dosya adını ayrı bir işlemde geri yükleyin.

(Çözüm https://stackoverflow.com/a/44036771/1389680 adresinden alınmıştır .)


7
Sadelik, kısalık,% 100 ... Bu cevap kamu hizmetidir ... görünürdeki her şeyi gözden
geçiriyor

1
Ne arasındaki fark moveve rename?
vovan

@vovan Bash'da mvher iki işlem için de kullanacağınızdan mı bahsediyorsunuz ? Dosyanın dizinini değiştirmeyi gerektirebilecek durum için 'move' kullanıyorum ve olmadığı durumlarda 'rename' kullanıyordum.
Robert Pollak

2
Bu (yeni) tarifi takip etmeye çalıştım ve işe yaramadı. Gerçek komutları göstermeniz yardımcı olabilir.
Greg Lindahl

1
@RobertPollak Bunun çeşitli versiyonlarını denedim ama işe yaramadı. "Dosyayı taşı" ile mi kastediyorsunuz git mv orig new? "Orijinali okudum" ile mi demek istiyorsun cp new orig && git add orig?
ᆼ ᆺ ᆼ
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.