2013-04-30 66 views
15

Dưới đây là một ví dụ đoạn ngắn (mà bạn có thể dán vào thiết bị đầu cuối Linux của bạn), tạo ra một kho lưu trữ mới git và thêm một số tập tin vào nó (sử dụng git phiên bản 1.7.9.5):Làm cho trạng thái git hiển thị các tệp được theo dõi chưa sửa đổi/không thay đổi?

cd /tmp/ 
mkdir myrepo_git 
cd myrepo_git/ 
git init 
git config user.name "Your Name" 
git config user.email [email protected] 
echo "test" > file_tracked_unchanged.txt 
echo "test" > file_tracked_changed.txt 
echo "test" > file_untracked.txt 
git add file_tracked_unchanged.txt 
git add file_tracked_changed.txt 
git commit -m "initial commit" 

Bây giờ, sau khi cam kết ban đầu, tôi muốn thay đổi các tệp file_tracked_changed.txt và giữ các tệp khác (ở đây, chỉ file_tracked_unchanged.txt) không thay đổi cho lần commit tiếp theo. Dưới đây là một đoạn trong đó chứng minh rằng, kết quả đầu ra và đa dạng của git status vs git ls-files (git sản lượng vỏ được bắt đầu bằng #):

echo "test more" >> file_tracked_changed.txt 

git status -uno 
# # On branch master 
# # Changes not staged for commit: 
# # (use "git add <file>..." to update what will be committed) 
# # (use "git checkout -- <file>..." to discard changes in working directory) 
# # 
# # modified: file_tracked_changed.txt 
# # 
# no changes added to commit (use "git add" and/or "git commit -a") 
git status 
# # On branch master 
# # Changes not staged for commit: 
# # (use "git add <file>..." to update what will be committed) 
# # (use "git checkout -- <file>..." to discard changes in working directory) 
# # 
# # modified: file_tracked_changed.txt 
# # 
# # Untracked files: 
# # (use "git add <file>..." to include in what will be committed) 
# # 
# # file_untracked.txt 
# no changes added to commit (use "git add" and/or "git commit -a") 
git status -uno --short 
# M file_tracked_changed.txt 
git status --short 
# M file_tracked_changed.txt 
# ?? file_untracked.txt 
git ls-files -v 
# H file_tracked_changed.txt 
# H file_tracked_unchanged.txt 

git add file_tracked_changed.txt 

git status -uno 
# # On branch master 
# # Changes to be committed: 
# # (use "git reset HEAD <file>..." to unstage) 
# # 
# # modified: file_tracked_changed.txt 
# # 
# # Untracked files not listed (use -u option to show untracked files) 
git status 
# # On branch master 
# # Changes to be committed: 
# # (use "git reset HEAD <file>..." to unstage) 
# # 
# # modified: file_tracked_changed.txt 
# # 
# # Untracked files: 
# # (use "git add <file>..." to include in what will be committed) 
# # 
# # file_untracked.txt 
git status -uno --short 
# M file_tracked_changed.txt 
git status --short 
# M file_tracked_changed.txt 
# ?? file_untracked.txt 
git ls-files -v 
# H file_tracked_changed.txt 
# H file_tracked_unchanged.txt 

Những gì tôi đang tìm kiếm, là một lệnh mà sẽ hiển thị tất cả các file được theo dõi trong một thư mục (trong đó git ls-files -v hiện), với trạng thái lưu trữ chính xác của chúng (mà git ls-files không hiển thị, vì nó hiển thị H làm trạng thái cho tất cả các tệp được theo dõi). Ví dụ, tôi muốn để có được một cái gì đó giống như giả:

git status-tracked 
# M file_tracked_changed.txt 
# . file_tracked_unchanged.txt 

... nơi dot . sẽ là biểu tượng cho thấy một sự theo dõi, nhưng tập tin không thay đổi (nếu tôi nhớ chính xác, SVN có thể sử dụng một nhân vật U cho những cái này).

Cuối cùng, tôi muốn cũng hiển thị trạng thái của tất cả các tập tin trong một thư mục, như trong giả:

git status-tracked-and-untracked 
# M file_tracked_changed.txt 
# . file_tracked_unchanged.txt 
# ?? file_untracked.txt 

... nhưng điều quan trọng hơn đối với tôi để có được tình trạng của tất cả các tệp được theo dõi, như trong pseudo git status-tracked ở trên.

Bất kỳ lệnh nào trong git, đã thực hiện điều gì đó như thế này?

+0

Hãy thử 'status git -sb' – Kartik

+2

Rất cám ơn những nhận xét @Kartik - nhưng lệnh đó hiển thị theo dõi được sửa đổi + không được theo dõi; Tôi đang tìm một lệnh cho thấy theo dõi sửa đổi + theo dõi chưa được sửa đổi. Chúc mừng! – sdaau

Trả lời

0
git status -s | egrep -v '^\?\?' 

Điều này lọc ra các dòng bắt đầu bằng ??, tức là các tệp không được theo dõi.

+1

Cảm ơn câu trả lời, @Andomar - nhưng không may, lệnh đó không hiển thị các tệp được theo dõi nhưng chưa sửa đổi, đó là những gì tôi yêu cầu. Chúc mừng! – sdaau

+1

'git ls-tree - tên-trạng thái HEAD' nên làm những gì bạn muốn, nhưng nó âm thầm bỏ qua phần' -status' :) – Andomar

+0

Rất cám ơn, @Andomar - mẹo tuyệt vời, tôi không có ý tưởng về 'ls-tree ', nhưng như bạn nói, các trạng thái không được hiển thị - vì vậy tôi vừa đăng [câu trả lời] (http://stackoverflow.com/a/16308182/277826) mà" xen kẽ "các trạng thái từ' git 'trạng thái' và 'ls-files'. Chúc mừng! – sdaau

3

Cảm ơn @Andomar, cho mẹo git ls-tree; đây là những gì nó cho thấy:

git ls-tree --name-status HEAD 
# file_tracked_changed.txt 
# file_tracked_unchanged.txt 

... nhưng tôi muốn trạng thái :)

 

OK, đây là một giải pháp, kêu gọi cả hai ls-filesstatus, và đan xen chúng với một chút bash phân tích cú pháp:

git ls-files -cdmoskt --abbrev=8 | while read -r line; do \ 
    fn=$(echo "$line" | sed 's/.*\s\(\w\+\)/\1/'); \ 
    st=$(git status -s "$fn" | printf "%-02s " $(sed 's/\([[:print:]]\+\)\s.*/\1/')); \ 
    echo "$st- $line"; \ 
done 

Nếu bạn chạy như trong ví dụ OP, bạn sẽ nhận được:

git ls-files -cdmoskt --abbrev=8 | while read -r line; do fn=$(echo "$line" | sed 's/.*\s\(\w\+\)/\1/'); st=$(git status -s "$fn" | printf "%-02s " $(sed 's/\([[:print:]]\+\)\s.*/\1/')); echo "$st- $line"; done 
# ?? - ? file_untracked.txt 
# M - H 100644 52e7a08e 0 file_tracked_changed.txt 
# - H 100644 9daeafb9 0 file_tracked_unchanged.txt 

... về cơ bản là những gì tôi muốn. (Tôi sẽ đăng lại đây nếu tôi có may mắn trong việc chuyển đổi điều này thành bí danh git).


EDIT: đây là git bí danh (đối với ~/.gitconfig):

ls-fstatus = "! cd $PWD/$GIT_PREFIX; git ls-files -cdmoskt --abbrev=8 | while read -r line; do \ 
    fn=$(echo \"$line\" | sed \"s/.*\\s\\([[:print:]]\\+\\)/\\1/\"); \ 
    st=$(git status -s "$fn" | printf \"%-02s \" $(sed \"s/\\([[:print:]]\\+\\)\\s.*/\\1/\")); \ 
    echo \"$st- $line\"; \ 
    done " 

... do đó, người ta chỉ có thể gọi git ls-fstatus trong thư mục con git repo nhất định.

+0

Điều này không xử lý các đường dẫn có dấu cách. Bằng cách thêm dấu ngoặc kép xung quanh đối số cho cd nó hoạt động: 'cd \" $ PWD/$ GIT_PREFIX \ ";' – KeithB

7

Cảm ơn @sdaau. Tôi đã thực hiện một vài thay đổi để nó chạy nhanh hơn nhiều, và mang lại kết quả trong các định dạng tương tự như git status:

git ls-files | while read -r line; 
do 
    st=$(git status -s "$line"); 
    if [ -n "$st" ]; then 
     echo "$st"; 
    else 
     echo " $line"; 
    fi; 
done 
+0

^Rất hữu ích, nhưng vẫn còn hơi chậm, bởi vì nó chạy một git_status cho mỗi tập tin duy nhất. – frnhr

1

Lấy cảm hứng từ @RogerDueck's answer, tôi đã thực hiện một kịch bản thực thi git ls-filesgit status chỉ một lần mỗi. Nó chạy nhanh hơn khoảng 15 lần trên repo của tôi với ~ 1700 tệp, chỉ dưới 2 giây.

EDIT: gia tăng một số bản sửa lỗi và một số unittests, chuyển đến GitHub: https://github.com/frnhr/git-fullstatus

Mẫu đầu ra:

M some/file 
D another/file 
D more/files/blahblah 
A this/is/an/added/file/i/think 
    an/unchanged_file 
    another/unchanged_file 
Các vấn đề liên quan