2008-10-22 29 views
16

Đây là loại theo dõi tới this question.Git: Tìm các đốm màu trùng lặp (tệp) trong cây này

Nếu có nhiều đốm màu có cùng nội dung, chúng chỉ được lưu trữ một lần trong kho lưu trữ git vì SHA-1 của chúng sẽ giống nhau. Làm thế nào sẽ đi về việc tìm kiếm tất cả các tập tin trùng lặp cho một cây nhất định?

Bạn có phải đi bộ cây và tìm kiếm các băm trùng lặp hay không git cung cấp các liên kết ngược từ mỗi đốm màu cho tất cả các tệp trong cây tham chiếu đến nó?

Trả lời

9

Chạy tính năng này trên codebase mà tôi làm việc là một thiết bị mở mắt tôi có thể cho bạn biết!

#!/usr/bin/perl 

# usage: git ls-tree -r HEAD | $PROGRAM_NAME 

use strict; 
use warnings; 

my $sha1_path = {}; 

while (my $line = <STDIN>) { 
    chomp $line; 

    if ($line =~ m{ \A \d+ \s+ \w+ \s+ (\w+) \s+ (\S+) \z }xms) { 
     my $sha1 = $1; 
     my $path = $2; 

     push @{$sha1_path->{$sha1}}, $path; 
    } 
} 

foreach my $sha1 (keys %$sha1_path) { 
    if (scalar @{$sha1_path->{$sha1}} > 1) { 
     foreach my $path (@{$sha1_path->{$sha1}}) { 
      print "$sha1 $path\n"; 
     } 

     print '-' x 40, "\n"; 
    } 
} 
+0

Bạn nói đúng ... Kết quả rất thú vị! – Readonly

+0

Chỉnh sửa nhỏ để hỗ trợ không gian trong đường dẫn của bạn: thay đổi kết thúc của regex từ "\ s + (\ S +) \ z" thành "\ s + (. +) \ Z". –

4

Câu trả lời kịch bản từ câu hỏi được liên kết của bạn cũng áp dụng khá nhiều ở đây.

Hãy thử lệnh git sau đây từ thư mục gốc của kho lưu trữ git của bạn.

git ls-tree -r HEAD 

Điều này tạo ra một danh sách đệ quy tất cả 'đốm màu' trong HEAD hiện tại, bao gồm cả đường dẫn và id sha1 của chúng.

git không duy trì liên kết ngược từ một blob đến cây để nó sẽ là một tác vụ kịch bản (perl, python?) Để phân tích đầu ra git ls-tree -r và tạo báo cáo tóm tắt về tất cả sha1 xuất hiện nhiều hơn một lần trong danh sách .

7

Chỉ cần tạo một lớp lót làm nổi bật các bản sao được hiển thị bởi git ls-tree.
Có thể hữu ích

git ls-tree -r HEAD | 
    sort -t ' ' -k 3 | 
    perl -ne '$1 &&/$1\t/ && print "\e[0;31m" ;/([0-9a-f]{40})\t/; print "$_\e[0m"' 
+0

Cảm ơn vì điều này! Rất tiện dụng. –

21
[alias] 
    # find duplicate files from root 
    alldupes = !"git ls-tree -r HEAD | cut -c 13- | sort | uniq -D -w 40" 

    # find duplicate files from the current folder (can also be root) 
    dupes = !"cd `pwd`/$GIT_PREFIX && git ls-tree -r HEAD | cut -c 13- | sort | uniq -D -w 40" 
+1

Ngắn & ngọt, cảm ơn. – sinelaw

0

More chung:

(for f in `find .`; do test -f $f && echo $(wc -c <$f) $(md5 -q $f) ; done) |sort |uniq -c |grep -vE '^\s*1\b' |sed 's/.* //' > ~/dup.md5 ; \ 
(for f in `find .`; do test -f $f && echo $(wc -c <$f) $(md5 -q $f) $f; done) |fgrep -f ~/dup.md5 |sort 
+0

Điều này dường như không trả lời câu hỏi, ở chỗ nó không tìm kiếm trong lịch sử Git. Cũng lưu ý đến 'find-type f' và' du'; phiên bản hiện tại của bạn là rất kém hiệu quả (đi qua các tập tin nhiều lần). Không downvoted vì điều này có thể hữu ích tôi đoán. – remram

0

Đối với người dùng Windows/PowerShell:

git ls-tree -r HEAD | group { $_ -replace '.{12}(.{40}).*', '$1' } | ? { $_.Count -gt 1 } | select -expand Group 

này kết quả đầu ra một cái gì đó như:

100644 blob 8a49bcbae578c405ba2596c06f46fabbbc331c64 filename1 
100644 blob 8a49bcbae578c405ba2596c06f46fabbbc331c64 filename2 
100644 blob c1720b20bb3ad5761c1afb6a3113fbc2ba94994e filename3 
100644 blob c1720b20bb3ad5761c1afb6a3113fbc2ba94994e filename4 
Các vấn đề liên quan