Trong git, có cách nào để hiển thị các tệp được lưu trữ không theo dõi mà không cần áp dụng tệp lưu trữ không?


100

Nếu tôi chạy git stash -u, tôi có thể lưu trữ các tệp không được theo dõi. Tuy nhiên, các tệp không được theo dõi đã nói không hiển thị cùng với git stash show stash@{0}. Có cách nào để hiển thị các tệp được lưu trữ không theo dõi mà không áp dụng lưu trữ không?

Câu trả lời:


121

Các tệp chưa được theo dõi được lưu trữ trong tệp gốc thứ ba của một cam kết lưu trữ. (Điều này không thực sự được ghi lại bằng tài liệu, nhưng khá rõ ràng từ The commit đã giới thiệu tính năng -u, 787513 ... và cách phần còn lại của tài liệu cho cácgit-stash cụm từ mọi thứ ... hoặc chỉ bằng cách thực hiện git log --graph stash@{0})

Bạn chỉ có thể xem phần "chưa được theo dõi" của kho thông qua:

git show stash@{0}^3

hoặc, chỉ bản thân cây "chưa được theo dõi", thông qua:

git show stash@{0}^3:

hoặc, một tệp "chưa được theo dõi" cụ thể trong cây, qua:

git show stash@{0}^3:<path/to/file>

Thật không may, không có cách nào tốt để có được bản tóm tắt về sự khác biệt giữa tất cả trạng thái theo giai đoạn + chưa theo giai đoạn + chưa theo dõi và trạng thái "hiện tại". nghĩa là: git show stash@{0}không thể được thực hiện để bao gồm các tệp chưa được theo dõi. Điều này là do bản thân đối tượng cây của bản cam kết lưu trữ, được gọi là stash@{0}:, không bao gồm bất kỳ thay đổi nào từ cấp độ gốc thứ ba, "không được phân giai đoạn".

Điều này là do cách áp dụng lại kho lưu trữ: các tệp được theo dõi có thể dễ dàng được áp dụng dưới dạng bản vá, trong khi các tệp không được theo dõi chỉ có thể được áp dụng, về lý thuyết, dưới dạng "toàn bộ tệp".


Vì vậy, cha mẹ của cam kết lưu trữ là (1. Kho lưu trữ cam kết được thực hiện dựa trên 2. Chỉ mục 3. Bản sao làm việc không được theo dõi) và bản thân cam kết lưu trữ có chứa bản sao hoạt động được theo dõi không? git stash showdường như hiển thị sự khác biệt giữa bản sao làm việc và # 1 (mã liên quan từ git-stash.sh:, git diff ${FLAGS:---stat} $b_commit $w_committrong đó $ b_commit là # 1 và $ w_commit là cam kết lưu trữ); có cách nào tích hợp sẵn git stash showđể bao gồm # 3 không?
Max Nanasy

Như bạn nói, tôi đã không tìm thấy một cách để có được một cái nhìn tóm tắt duy nhất của một stash, nhưng bạn có thể thấy thông tin đầy đủ của nó trong một lệnh với: git log --graph --topo-order -m -u. matthewlmcclure.com/s/2014/01/10/…
Matt McClure

4
Lưu ý rằng bạn sẽ gặp một lỗi xấu ( fatal: ambiguous argument 'stash@{0}^3': unknown revision or path not in the working tree.) nếu bạn không thực sự có các tệp chưa được theo dõi trong kho lưu trữ đó (nhưng bạn đã nghĩ là có).
Randall

2
@antak: nope, git stash showkhông không hiển thị các tập tin untracked (true ít nhất git 2.7.4):
Norbert Bérci

1
Lưu ý (2.13.2-linux): git stash poptrước tiên sẽ cố gắng khôi phục các tệp chưa được theo dõi, sau đó cố gắng khôi phục các tệp đã theo dõi. Nếu thao tác thứ hai không thành công (ví dụ: xung đột), thì thao tác đầu tiên không được khôi phục lại (kho lưu trữ tệp chưa được kiểm soát sẽ giữ nguyên nhưng tệp không bị xóa khỏi đĩa), vì vậy ngay cả khi bạn khắc phục được xung đột, cửa sổ bật lên tiếp theo sẽ không thành công dù sao.
Marinos An

22

Bạn có thể liệt kê tất cả các cam kết lưu trữ bằng lệnh sau:

git rev-list -g stash

Vì các kho lưu trữ được biểu diễn dưới dạng cam kết hợp nhất 3 chiều của HEAD, chỉ mục và cam kết "gốc" không có phụ huynh của các tệp chưa được kiểm soát, các tệp lưu trữ chưa được kiểm soát có thể được liệt kê bằng cách nối kết quả đầu ra ở trên vào như sau:

git rev-list -g stash | git rev-list --stdin --max-parents=0

Các ứng dụng hữu ích ở trên:

Chỉ hiển thị các tệp được lưu trữ, chưa được theo dõi

git rev-list -g stash | git rev-list --stdin --max-parents=0 | xargs git show --stat

Tất nhiên, hãy xóa --statđể xem nội dung của các tệp.

Tìm một tệp cụ thể

git rev-list -g stash | xargs -n1 git ls-tree -r | sort -u | grep <pattern>

Grep các tệp không được theo dõi

git rev-list -g stash | git rev-list --stdin --max-parents=0 | xargs git grep <pattern>

Liệt kê tất cả nội dung của tất cả các kho lưu trữ

git rev-list -g stash | git rev-list --stdin | xargs git show --stat

10

Để liệt kê các tệp chưa được theo dõi trong kho lưu trữ:

git ls-tree -r stash@{0}^3 --name-only

Để hiển thị sự khác biệt hoàn toàn của tất cả các tệp chưa được theo dõi (có nội dung):

git show stash@{0}^3

Các lệnh này đọc kho cuối cùng (gần đây nhất). Đối với các kho lưu trữ trước đó, hãy tăng số phía sau "stash @", ví dụ: stash@{2}cho số thứ hai từ kho cuối cùng.

Lý do điều này hoạt động là git stashtạo ra một cam kết hợp nhất cho mỗi kho lưu trữ, có thể được tham chiếu là stash@{0}, stash@{1}v.v. Cấp độ gốc đầu tiên của cam kết này là HEAD tại thời điểm lưu trữ, cấp độ gốc thứ hai chứa các thay đổi đối với các tệp được theo dõi và thứ ba (có thể không tồn tại) các thay đổi đối với các tệp không được theo dõi.

Điều này được giải thích một phần trong trang chủ dưới "Thảo luận" .


5

Để xem tất cả các tệp trong kho lưu trữ (cả được theo dõi và chưa được theo dõi), tôi đã thêm bí danh này vào cấu hình của mình:

showstash = "!if test -z $1; then set -- 0; fi; git show --stat stash@{$1} && git show --stat stash@{$1}^3 2>/dev/null || echo No untracked files -"

Nó có một đối số duy nhất về kho mà bạn muốn xem. Lưu ý rằng nó sẽ vẫn hiển thị nó trong hai danh sách giáp nhau.

Các if...fiphần thay đổi đối số bash $ 1-0 nếu không được thông qua.


5

Một cách giải quyết: Sắp xếp các tệp trước khi lưu trữ chúng sẽ git stash show -phoạt động như mong đợi.

git add .
git stash save

Lưu ý: Cách này cũng mang lại sức mạnh cho việc thêm các phần tương tác, đây là cách thực hiện .
Thận trọng: Đảm bảo rằng bạn không có công việc được dàn dựng trước đó, nếu không bạn sẽ không thể phân biệt được.
Điều này có thể được sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.