Tüm CRLF'yi LF'ye değiştirmek için git geçmişini yeniden yaz?


32

Özel Git deposunu win32 kutusundan Ubuntu'ya aktaracağım. Son bir dos2unix işlemi yapabilsem de, tüm tarihi yeniden yazmak istiyorum, bu yüzden bazı Git GUI log / diff'i doğru gösterecektir. Örneğin, gitg her CR / LF için boş satır ekler.

Yanıtlar:


25

Bunun git filter-branchiçin, --tree-filterseçeneği ile ve --allşube için belirterek kullanabilirsiniz .

İşte bir örnek (Unix tipi bir metin dosyası ile boş bir dizinde başlatılmış:

Hazırlık:

$ hexdump -C testfile 
00000000  61 0d 0a 62 0d 0a 63 0d  0a                       |a..b..c..|
00000009

$ git init
Initialized empty Git repository in /home/seigneur/tmp/a/.git/

$ git add testfile && git commit -m "dos file checked in"
[master (root-commit) df4970f] dos file checked in
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 testfile

Komuta:

$ git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all

Çıktı:

Rewrite df4970f63e3196216d5986463f239e51eebb4014 (1/1)dos2unix: converting file testfile to Unix format ...

Ref 'refs/heads/master' was rewritten

$ hexdump -C testfile 
00000000  61 0a 62 0a 63 0a                                 |a.b.c.|
00000006

Ben kuvvetle önceden tam yedekleme yapıyor tavsiye . Bunu Linux makinenizden çalıştırmak (windows ortamınızda iyi bir kabuk kurulmamışsa) muhtemelen daha kolaydır.

Düzenleme: dönüşüm ilk kez tersine çevrildi.


1
Teşekkürler, bu yazı bana çok yardımcı oldu. Ben orijinal komuta küçük bir değişiklik düzelttim, kendi adlarına boşluk ile birkaç dosya vardı: git filter-branch --tree-filter 'git ls-files -z | xargs -0 dos2unix' -- --all. Bayraklar -zve -0anlatmak git ls-filesve xargsyazdırmak ve yorumlamak için nullsatırın sonuna kadar.
Ivan

Dos2unix komutunun bir diğer alternatifi ise gitine güvenmektir:git filter-branch --prune-empty --tree-filter 'git add --renormalize .' -- --all
Vilmantas Baranauskas

6

Mat'ın cevabı bu konuyu baştan aşağı çekti. Ne yazık ki Ubuntu Linux'ta sürüm 10.04'ten (Lucid Lynx) başlayarak, dos2unix / unix2dos komutları artık kullanılamaz ve yerine todos / todos kullanılamaz. Dahası, dönüşüm komutlarının her iki kümesi de ikili dosyaların varlığına ilişkin cehalet derecesine sahip değildir, bu nedenle eğer deponuzda görüntüler, yazı tipleri, vb. Varsa, bunlar bu işlem tarafından bozulmuş olacaktır.

Aşağıda gösterildiği gibi yalnızca metin dosyalarını doğru şekilde tanımlamak ve işlemek için Linux 'file' komutunu kullanan ikili dosya bozulması sorunu için bir geçici çözüm bulabildim. Aşağıdaki komut, varolan etiketleri yeni değiştirilen taahhütlere taşıyarak korumak için --tag-name-filter seçeneğini kullanır. Ayrıca, komutun daha önce havuzunuzda tree-filter kullanmanız durumunda çalışacağından emin olmak için --force flag'ı kullanır.

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs fromdos' --tag-name-filter cat -- --all

3

Ve herhangi bir ek araç olmadan ('fromdos', 'dos2unix' vb.):

git filter-branch --force --tree-filter 'git ls-files | xargs file | sed -n -e "/.*: .*text.*/s/\(.*\): .*/\1/p" | xargs -0 sed -i"" -e "s/"$(printf "\015")"$//"' --tag-name-filter cat -- --all

Crossplatform (OS X, FreeBSD, Linux) kullanışlı analog 'fromdos', 'dos2unix':

sed -i'' -e 's/'"$(printf '\015')"'$//'

Belki de faydalı 'unix2dos':

sed -i '' -e 's|$|'"`printf '\015'`"'|' file.name

Ne yaptığınızı kesin olarak söylerseniz, bu basit satır içi komutu "/ r" yi geçerli dizindeki tüm dosyalardan silmek için kullanabilirsiniz.

find . -type f -exec sed -i'' -e 's/'"$(printf '\015')"'$//' {} \;

1
Aksine \ r değiştirmek \ n r sadece \ kaldırmak yerine \ n için
xdevs23

Karşılık gelen sedçağrıların daha kısa sed -n -e "s/\(.*\): .*text.*/\1/p"
olanlarla
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.