Làm cách nào để tìm cam kết git gần đây nhất đã sửa đổi một tệp?


180

Tôi muốn tìm cam kết gần đây nhất đã sửa đổi một tệp nguồn.

Tôi có thể sử dụng git blameđể xem tất cả các ngày cho các cam kết theo từng dòng, nhưng thật khó để biết chính xác cam kết nào là lần cuối cùng chạm vào tệp.

Làm cách nào tôi có thể tìm thấy cam kết cuối cùng đã chạm vào một tệp đã cho trong kho git của mình?

Câu trả lời:


230

git log hỗ trợ xem lịch sử của các tệp cụ thể (và thư mục), vì vậy bạn có thể gọi nó như thế này:

git log my/file.c

Nếu bạn thực sự chỉ muốn liệt kê một cam kết gần đây nhất, ví dụ để sử dụng nó trong một tập lệnh, hãy sử dụng -n 1tùy chọn:

git log -n 1 --pretty=format:%H -- my/file.c

--pretty=format:%hnói git logđể chỉ hiển thị băm cam kết. Dấu --phân cách ngăn tên tệp không được hiểu là tên cam kết, chỉ trong trường hợp không rõ ràng.


12
Nếu bạn muốn biết lần cuối cùng một tệp được sửa đổi bất kể chi nhánh, bạn có thể xem xét tất cả các chi nhánh bằng cách thêm --alltùy chọn.
KC

44

Nếu bạn chỉ muốn tìm cam kết gần đây nhất, thì bạn không muốn git-log, git-rev-listtrong đó liệt kê các đối tượng cam kết thay đổi tệp đó, trong đường dẫn cam kết đó, bắt đầu bằng lần gần nhất (theo thời gian). Chỉ cần đặt:

git rev-list -1 <commit> <filename>

Đối với git-rev-listtrường hợp của bạn, bạn chỉ cần cung cấp:

  • Số lượng cam kết bao gồm, hoặc -1 chỉ cho gần đây nhất,
  • Các chi nhánh (hoặc cam kết id) để bắt đầu nhìn lại từ, TRỤ nếu bạn đã có trên nó, hoặc --all nếu bạn muốn tất cả các cam kết được biết đến, và
  • Đường dẫn tương đối đến tập tin của bạn.

Điều này chỉ trả về ID xác nhận gần đây nhất trong nhánh hiện tại để thay đổi tệp đó, ví dụ: 215095e2e338525be0baeeebdf66bfbb304e7270

Đối với một ví dụ phức tạp hơn, bạn có thể sử dụng tên thẻ và thậm chí các tham chiếu từ xa và bao gồm tên đường dẫn tương đối với ký tự đại diện, ví dụ:

git rev-list origin/user/bob/testbranch -1 src/bfiles/*.txt

... Điều này sẽ cho bạn biết sự thay đổi gần đây nhất đối với trận đấu ký tự đại diện trong lịch sử của chi nhánh đó. Các tùy chọn cho danh sách rev là cực kỳ, nó là một trong những lệnh hệ thống ống nước quan trọng nhất, vì vậy bạn có thể bao gồm hoặc loại trừ bằng bất kỳ tiêu chí nào bạn có thể tưởng tượng.

Tất nhiên, tham khảo trang Hướng dẫn git-rev-list (1) .


Bạn thực sự không giải thích tại sao sử dụng git-loglà kém hơn.
Piotr Dobrogost

7
Tôi sẽ không nói kém hơn, chỉ là nó cung cấp thông tin không liên quan theo mặc định. git-rev-list chỉ trả về ID cam kết, đó là những gì bạn muốn nếu bạn định đưa phản hồi vào tập lệnh hoặc quy trình tự động hóa khác. git-log trả về thông tin về các xác nhận đã chọn, trước tiên bằng cách sử dụng git-rev-list để thu thập các id xác nhận, sau đó thu thập thông tin trên mỗi cam kết. Nếu bạn chỉ lọc ra thông tin cam kết và sử dụng id, thì bạn chỉ có thể sử dụng git-rev-list ở vị trí đầu tiên. Vì nhật ký được dựa trên danh sách rev, nên nó chiếm hầu hết các tham số bộ lọc giống nhau.
Michael Erickson

3
git-loglà sứ, git-rev-listlà hệ thống ống nước.
blitzen9872

27

Nếu bạn muốn lấy hàm băm của cam kết mới nhất để sửa đổi một tập hợp tệp cụ thể (và muốn tránh awk), bạn có thể sử dụng:

git log -n 1 --pretty=format:%h -- <path>

Điều này có thể hữu ích để có được hàm băm cam kết sau đó sử dụng với git describe.

Ví dụ (trong trường hợp nó hữu ích cho bất cứ ai)

Tôi tạo id phiên bản hiện tại bằng cách xem xét cam kết mới nhất để thay đổi bất kỳ tệp nguồn nào (giả sử bạn đánh dấu các phiên bản bằng các thẻ như mycode-1.2.1):

COMMIT=$(git log -n 1 --pretty=format:%h -- *.c *.h)
if VN=$(git describe --always --abbrev=5 --match "mycode-*" $COMMIT 2>/dev/null) &&
case "$VN" in
mycode-*)
    git update-index -q --refresh
    test -z "$(git diff-index --name-only HEAD *.c *.h)" ||
    VN="$VN-mod" ;;
*) VN="mycode-unknown-g$VN" ;;
esac
then
    continue
else
VN="mycode-unknown"
fi

Điều này tạo ra các id như:

  • mycode-1.2.1 - khi trạng thái hiện tại của các tệp nguồn tương ứng với phiên bản được gắn thẻ
  • mycode-1.2.1-g3k7s2 - khi trạng thái hiện tại của các tệp nguồn tương ứng với cam kết theo phiên bản được gắn thẻ
  • mycode-1.2.1-g3k7s2-mod - khi trạng thái hiện tại của các tệp nguồn đã được sửa đổi kể từ lần xác nhận cuối cùng sau phiên bản được gắn thẻ
  • mycode-unknown - khi chưa có thẻ phiên bản được tạo

5
$VNtrông giống như một cơn ác mộng bất tử SVN
ThorSummoner

10

Tôi không chắc đây có phải là điều bạn muốn không nhưng nếu bạn thực hiện git log <thefile>để có được các cam kết đã thay đổi tệp đó. Bạn có thể chọn một trong những trên cùng. Nó nên là một trong những bạn đang tìm kiếm.


4
nếu bạn sử dụng git log -n1 -- <thefile>(hoặc chuyển đầu ra sang head -1nếu bạn muốn lãng phí tài nguyên), bạn không phải chọn thủ công dòng trên cùng (xem câu trả lời của Jo Liss )
Tobias Kienzler

4
Điểm tốt. Tôi nghĩ bạn cũng có thể bỏ qua -nvà sử dụng -1trực tiếp.
Noufal Ibrahim

3

Để chỉ nhận được giới thiệu trên một dòng, hãy thử:

git log -n1 --oneline <path> | awk '{print $1;}'

2

Khi bạn có id SHA của cam kết bạn muốn xem xét sử dụng git log FILENAME, bạn sẽ có thể thực hiện git show SHA_ID_HEREđể xem những gì bạn đã làm cho cam kết cụ thể đó. Bạn thậm chí không cần nhập toàn bộ ID; 6 ký tự đầu tiên là đủ.


4
đó là nhiều hơn một chút so với OP yêu cầu, nhưng FYI bạn có thể kết hợp điều này thành một lớp lót:git show $(git log -1 --pretty="%H" -- FILENAME)
Tobias Kienzler
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.