2015-09-08 15 views
8

Git được dựa trên nội dung và không có tập tin vì vậy tôi đang hiểu các hành vi sau đây nhưng tôi muốn biết nếu có một tùy chọn đặc biệt hoặc hack để phát hiện điều như vậy:Git làm thế nào để phát hiện toàn bộ thư mục bị xóa/di chuyển

git init 
mkdir -p foo/bar 
echo "test" foo/a.txt 
echo "test2" foo/bar/b.txt 
git add -A 
git commit -m "test" 

rm -fr foo 
git add -A 
git commit -m "delete whole dir" 
git log --name-status 

Khi tôi kiểm tra đăng nhập, Git sẽ không nói rõ với tôi rằng foo đã bị xóa nhưng tất cả tập tin foo/a.txtfoo/bar/b.txt đã bị xóa

commit d1513a9b36cd546371a194e798566c49e779e3a9 
Date: Tue Sep 8 16:58:21 2015 +0200 

    delete whole dir 

D  foo/a.txt 
D  foo/bar/b.txt 

commit 135f7ae52dfddcee5eeb7bdfa9f0d5c924fed3af 
Date: Tue Sep 8 16:58:10 2015 +0200 

    test 

A  foo/a.txt 
A  foo/bar/b.txt 

Vì vậy, nếu tôi có thể tạo các cam kết sau:

mkdir -p foo/bar 
echo "test" > foo/a.txt 
echo "test2" > foo/bar/b.txt 
echo "test3" > foo/bar/c.txt 
git add -A 
git commit -m "test2" 

rm -f foo/a.txt foo/bar/b.txt 
git add -A 
git commit -m "delete just 2 files" 
git log --name-status 

name-status giữa cam kết delete whole dirdelete just 2 files tương tự

commit 92564fb59464fd6bba2766a6d488c2ff8ca967ea 
Date: Tue Sep 8 17:03:09 2015 +0200 

    delete just 2 files 

D  foo/a.txt 
D  foo/bar/b.txt 

commit 3b13f27e960c4ec66464e8a1e0d23f038a872564 
Date: Tue Sep 8 17:02:50 2015 +0200 

    test2 

A  foo/a.txt 
A  foo/bar/b.txt 
A  foo/bar/c.txt 

Có cách nào để phát hiện sự khác biệt khi toàn bộ thư mục bị xóa?

+0

Tôi không nghĩ rằng đó là cách để phát hiện sự khác biệt – edi9999

+0

Không, bạn không thể làm điều đó – Bijendra

Trả lời

3

Giả sử một cấu trúc cây mẫu trong kho lưu trữ của bạn như:

Initial commit 

Changes to be committed: 
    (use "git rm --cached <file>..." to unstage) 

    new file: a/b/c/d/e/q.txt 
    new file: a/b/c/m.txt 
    new file: a/b/c/n.txt 
    new file: a/b/f/o.txt 
    new file: a/b/f/p.txt 
    new file: a/b/k.txt 
    new file: a/b/z.txt 
    new file: a/x.txt 
    new file: a/y.txt 

Hãy làm cho các cam kết sau:

commit 0bb4d4d50072c1eac1c3cb2b14b670deba8ee31b 
Author: Site User <[email protected]> 
Date: Tue Sep 8 19:27:58 2015 +0100 

    removed a/b/c/d/e/q.txt 

D  a/b/c/d/e/q.txt 

-

commit 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a 
Author: Site User <[email protected]> 
Date: Tue Sep 8 19:28:55 2015 +0100 

    removed a/b/c/m.txt and a/b/c/n.txt (full a/b/c) 

D  a/b/c/m.txt 
D  a/b/c/n.txt 

-

commit 3af8ace473944996fb8b21135106360305e8b89a 
Author: Site User <[email protected]> 
Date: Tue Sep 8 19:30:30 2015 +0100 

    added a/b/g/w.txt 

A  a/b/g/w.txt 

-

Commit 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a là một trong đó nhìn thấy thư mục "a/b/c" biến mất, như các tập tin cuối cùng trong nó được lấy ra.

Để tìm SHA # của cam kết khi thư mục a/b/c đã bị xóa, bạn có thể tìm thấy cam kết cuối cùng liên quan đến "a/b/c" thư mục bằng cách sử dụng một sự kết hợp của:

#> git log --name-status -- a/b/c 

#> git ls-tree -r [commit] -- a/b/c 

Cái gì như:

for cmt in $(git log --pretty=%H -- a/b/c); \ 
    do X=$(git ls-tree -r "${cmt}" -- a/b/c); \ 
    [[ -z "${X}" ]] && echo "The folder a/b/c has been deleted in commit: ${cmt}"; \ 
done 

Output:

The folder a/b/c has been deleted in commit: 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a 

Trong một hình thức kịch bản BASH đơn giản (mà tôi đặt tên deleted.sh, nên có quyền thực thi):

#!/bin/bash 

P="$1" 
GIT=$(which git) 

for cmt in $($GIT log --pretty=%H -- "${P}"); do 
    X=$($GIT ls-tree -r "${cmt}" -- "${P}"); 
    [[ -z "${X}" ]] && echo "The folder a/b/c has been deleted in commit: ${cmt}"; 
done 

Cách sử dụng:

./deleted.sh a/b/c 

Kết quả:

The folder a/b/c has been deleted in commit: 3b53f16eb2fd7d3d605180ccabcfa71eb9e9225a 

Làm thế nào nó hoạt động

Đầu tiên cam kết, sẽ trở lại trong lịch sử, mà không có tập tin trong cây phù hợp với các đường dẫn thư mục, nên làm.

Đó là những gì kịch bản trình bao đang thực hiện.

Nó lặp lại trong lịch sử, truy xuất tất cả các SHA có liên quan đến bất kỳ tệp nào trong thư mục và sau đó tìm thấy - trong số các tệp đó - đầu tiên không có bất kỳ tệp nào khớp với đường dẫn được cung cấp, cây Git.

Thực tế là cam kết đó sẽ xuất hiện trong danh sách để kiểm tra, đảm bảo rằng có những thay đổi, trong đó, liên quan đến thư mục.

Thực tế là không có tệp nào khớp với thư mục trong cây của nó (lọc "ls-tree" trả về một chuỗi rỗng), đảm bảo rằng đó là cam kết trong đó tệp cuối cùng trong thư mục đó đã bị xóa.

+0

Nhưng cam kết cuối cùng từ thư mục không cần thiết có nghĩa là thư mục đó đã bị xóa? – Kakawait

+0

Cam kết đầu tiên, quay trở lại lịch sử, không có tệp nào trong cây phù hợp với đường dẫn thư mục, nên làm. Đó là những gì kịch bản shell đang làm. Nó lặp lại trong lịch sử, lấy tất cả các SHA có liên quan đến bất kỳ tập tin nào trong thư mục, và sau đó tìm thấy - trong số các commit đó, cái đầu tiên không có bất kỳ tệp nào khớp với đường dẫn được cung cấp trong cây Git. –

+0

@Kakawait, vui lòng xem ghi chú về "Cách hoạt động" như giải thích. –

1

Theo như tôi biết, không có lệnh git đặc biệt nào để phát hiện xem thư mục đã bị xóa/di chuyển chưa.

Tuy nhiên, nếu toàn bộ thư mục đã di chuyển đến vị trí mới trong kho lưu trữ git được theo dõi, nó sẽ hiển thị trong phần Untracked files: của lệnh git status. Ngoài ra, tất cả các tệp của nó sẽ hiển thị là đã xóa.

Đối với thư mục đã xóa, nếu bạn mong muốn thư mục không còn tồn tại, bạn có thể chạy lệnh ls để kiểm tra kỹ xem thư mục có bị xóa hay không. Nếu thư mục không có ở đó, nó không được theo dõi.

Nếu thư mục tồn tại nhưng không chứa gì, thì git cũng không theo dõi nó. Tuy nhiên, bạn có thể thử

git ls-files dirName/ --error-unmatch; echo$?

Giải pháp này ban đầu được đề cập trên this StackOverflow question. Lệnh này được yêu cầu kiểm tra xem một tập tin cụ thể có bị git theo dõi hay không nhưng trong trường hợp này git sẽ kiểm tra xem có bất kỳ tệp nào trong đó dirName là một phần của đường dẫn tệp. Nếu thư mục không được theo dõi thì một lỗi sẽ xuất hiện.

+0

'git ls-files' là một chìa khóa! Cảm ơn sự đóng góp của bạn (: upvote :) – Kakawait

+0

'git ls-files' là một chìa khóa! Cảm ơn sự đóng góp của bạn (: upvote :) – Kakawait

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