2010-10-28 27 views
50

Tôi có một dự án theo số git. Một ngày, tôi đã chuyển tất cả các tệp dự án từ thư mục hiện tại sang foo/bar/ trong dự án. Tôi đã làm điều đó bằng cách sử dụng git mv. Sau đó, tôi đã thêm một số tệp khác và đã thực hiện một số thay đổi đối với các tệp hiện có.Làm thế nào tôi có thể viết lại lịch sử để tất cả các tệp, ngoại trừ các tệp tôi đã di chuyển, nằm trong thư mục con?

Kết quả là, bây giờ khi tôi xem lịch sử của foo/bar/file.c, tôi chỉ có thể thấy những thay đổi mà tôi đã làm sau khi tôi di chuyển tệp.

Tôi đã cố sửa lỗi này theo nhiều cách khác nhau (filter-branch với bộ lọc thư mục con, v.v.), nhưng không có gì hữu ích, vì vậy tôi đã xếp chồng lên nhau ở đây. Tôi sẽ đánh giá cao bất kỳ sự giúp đỡ nào mà bạn có thể cho tôi. Cảm ơn!

Trả lời

85

Để viết lại lịch sử với các tập tin chuyển:

Nếu bạn muốn lịch sử của dự án để trông như thể tất cả các file đã luôn trong thư mục foo/bar, thì bạn cần phải làm một phẫu thuật nhỏ. Sử dụng git filter-branch với "bộ lọc cây" để viết lại các cam kết để bất cứ nơi nào foo/bar không tồn tại, nó được tạo ra và tất cả các tập tin được chuyển tới nó:

git filter-branch --prune-empty --tree-filter ' 
if [ ! -e foo/bar ]; then 
    mkdir -p foo/bar 
    git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar 
fi' 

Bây giờ lịch sử sẽ được ghi lại như thể tất cả các file đã luôn luôn nằm ở foo/bar.

Để xem lịch sử của một tập tin di chuyển:

Nếu bạn chỉ muốn xem lịch sử của một tập tin đó đã được di chuyển hoặc đổi tên tại một số điểm trong quá khứ, sau đó chỉ cần sử dụng tùy chọn --follow để git log:

git log --follow foo/bar/file.c 
+1

@Alexander: Bạn có thể thử đặt một lớp lót (tất cả mọi thứ trong dấu nháy đơn) trong một tập lệnh thực tế, với dòng bash shebang. Tôi nghĩ 'filter-branch' có lẽ đang cố gắng chạy nó trong' sh', không phải 'bash'. – Cascabel

+0

Tôi đã thực hiện một số tiến bộ. Dường như dấu ngoặc kép trong câu lệnh if đã gây ra lỗi này. Dấu ngoặc đơn hoạt động tốt hơn, nó vẫn không hoạt động. Vấn đề là trước khi tôi chuyển mọi thứ sang foo/bar/tôi có thư mục có tên foo với một số nội dung trong dự án. Vì vậy, bây giờ nó than phiền "không thể di chuyển' foo 'vào một thư mục con của chính nó, 'foo/bar/foo'". –

+0

@Alexander: Bạn chỉ cần điều chỉnh tập lệnh tương ứng. Một cái gì đó như: 'if [[! -e foo/bar]]; sau đó mkdir -p foo/bar; git ls-tree - tên chỉ $ GIT_COMMIT | grep -v^foo $ | xargs -I tập tin mv tập tin foo/bar; fi' Điều đó sử dụng grep để lọc ra 'foo' khỏi danh sách các tập tin cần di chuyển. Lưu ý rằng tôi cũng giả sử rằng thư mục con 'bar' không bao giờ tồn tại cho đến khi bạn di chuyển mọi thứ bên dưới nó. Nếu đó không phải là trường hợp, thì bạn cũng cần tính đến điều đó trong kịch bản. –

6

Để quấn thứ ở đây là một bản tóm tắt ngắn về những gì tôi đã làm. Lệnh làm việc cho tôi là:

if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo ""; fi 

Lệnh echo mà tôi đã thêm vào cuối đảm bảo rằng ngay cả khi lệnh mv toàn bộ sẽ tiếp tục chạy. Nó không di chuyển nội dung của foo/bar/foo, nhưng tôi có thể sống với điều đó.

Cảm ơn rất nhiều đến Dan Moulding (!!!) và Jefromi để được trợ giúp.

Các vấn đề liên quan