Git: Hiển thị tất cả các thay đổi khác nhau đối với một dòng duy nhất trong một tệp được chỉ định trên toàn bộ lịch sử git


112

Tôi đã nhìn xung quanh và không chắc liệu điều này có khả thi không, nhưng đây là:

Tôi có một tệp (javascript) (giả sử /lib/client.js) trong đó tôi có một số nhận dạng duy nhất được chỉ định cho một biến, như sau: var identifier = "SOME_IDENTIFIER";

Bạn có thể coi số nhận dạng giống như số phiên bản: Theo định kỳ, chúng tôi sẽ thay đổi biến này thành số nhận dạng mới.

Điều tôi muốn làm là tìm tất cả các số nhận dạng duy nhất mà chúng tôi đã từng sử dụng. Làm thế nào tôi có thể làm điều này với git?

Tôi tưởng tượng có thể có một cách để tìm kiếm thông qua lịch sử git và in khớp dòng "var identifier =". Tôi có thể xóa danh sách này theo cách thủ công.

Dù sao, tôi đánh giá cao bất kỳ cái nhìn sâu sắc nào ở đây. Cảm ơn.


Câu trả lời:


106

Kể từ git 1.8.4 , có một cách trực tiếp hơn để trả lời câu hỏi của bạn.

Giả sử dòng đó 110là dòng nói var identifier = "SOME_IDENTIFIER";, thì hãy làm như sau:

git log -L110,110:/lib/client.js

Điều này sẽ trả về mọi cam kết đã chạm vào dòng mã đó.

[ Tài liệu Git (xem tham số dòng lệnh "-L")]


49

Xem trang người đàn ông cho git-loggitdiffcore. Tôi tin rằng lệnh này sẽ làm được điều đó, nhưng nó có thể không đúng lắm:

git log -G "var identifier =" file.js

CHỈNH SỬA: Đây là một khởi đầu sơ bộ cho một tập lệnh bash để hiển thị các dòng thực tế. Đây có thể là những gì bạn đang tìm kiếm.

for c in $(git log -G "something" --format=%H -- file.js); do
    git --no-pager grep -e "something" $c -- file.js
done

Nó sử dụng git log -Gđể tìm các cam kết thú vị, sử dụng --format=%Hđể tạo ra một danh sách các băm cam kết. Sau đó, nó lặp lại từng cam kết thú vị, yêu cầu git grephiển thị các dòng từ cam kết đó và tệp chứa regex, được mở đầu bằng băm cam kết.


EDIT: Đã thay đổi để sử dụng -Gthay vì -Snhư được đề xuất trong nhận xét.


@ Rob - nhờ cho điều này - chỉnh sửa nhỏ để kịch bản của bạn mặc dù - đưa chỉ là tên tập tin chỉ hiển thị các cam kết mà chỉ ảnh hưởng đến tập tin đó - nếu một cam kết tham chiếu các file khác nó không được liệt kê
Adrian Cornish

@AdrianCornish - Rất vui vì nó hữu ích. Tôi nghĩ OP muốn chỉ xem xét một tệp, nhưng bạn hoàn toàn chính xác rằng việc xóa tên tệp có lẽ là một script hữu ích hơn.
cướp

Tôi có một tình huống khó khăn hơn. Tệp được đề cập đã chuyển từ tệp paht_a / sang tệp path_b /. Bây giờ khi tôi làm điều đó trong path_b, nó chỉ hiển thị những thay đổi khi tệp chuyển từ path_a sang path_b. Nếu tôi làm điều đó trong path_a, nó sẽ cho tôi biết là: đối số không rõ ràng 'tệp': bản sửa đổi không xác định hoặc đường dẫn không có trong cây làm việc.
Andy Song

@AndySong - Nếu chuỗi bạn đang tìm kiếm đủ duy nhất, có lẽ bạn có thể loại bỏ tên tệp và vẫn nhận được những gì bạn đang tìm kiếm.
cướp

Thuận tiện hơn cho tôi - hãy đặt một dòng trống sau mỗi lần cam kết, liệt kê các dòng:sfile=path/to/some_file; sfind='string_to_find'; for c in $(git log -G $sfind --format=%H -- $sfile); do git --no-pager grep -e $sfind -n $c -- $sfile; echo; done
John_West

14

Bạn cũng có thể làm điều này với gitk:

gitk file.js

Trong trình đơn thả xuống "cam kết", hãy chọn "thêm / xóa chuỗi:" và trong hộp văn bản bên cạnh, nhập "var origin =" và mọi cam kết thêm hoặc xóa các dòng chứa chuỗi đó sẽ được đánh dấu.


Điều này đã giúp xác định cam kết mà tại đó dòng chứa "var IDfier =" đã được thêm vào, nhưng nó không hiển thị các cam kết tiếp theo đã sửa đổi dòng này.
findchris

2
Bạn đã thử git blame file.jshoặc git gui blame file.js?
Ethan Brown,

1
Tôi biết git đổ lỗi làm gì; Tôi đang tìm kiếm một lịch sử đầy đủ của các bản sửa đổi, không phải là một khác biệt.
findchris

1
git gui blame file.jssẽ làm điều đó ... nó sẽ hiển thị cho bạn tất cả các bản sửa đổi của một tệp và ai đã thay đổi nó; bạn chỉ có thể nhấp chuột ngược qua lịch sử.
Ethan Brown,

Tôi đã kết thúc việc xem xét trực quan bằng gitk. Tôi tưởng tượng có một số kỹ thuật git thanh lịch để làm điều này, nhưng gitk đã đủ tốt. Cảm ơn.
findchris

9

Nếu bạn điều chỉnh câu trả lời của @ rob chỉ một chút, git logvề cơ bản sẽ làm điều này cho bạn, nếu tất cả những gì bạn cần là so sánh trực quan:

git log -U0 -S "var identifier =" path/to/file

-U0có nghĩa là đầu ra ở chế độ vá ( -p) và hiển thị không dòng ngữ cảnh xung quanh bản vá.

Bạn thậm chí có thể làm điều này trên các chi nhánh:

git log -U0 -S "var identifier =" branchname1 branchname2 -- path/to/file

Có thể có một cách để ngăn chặn tiêu đề khác biệt, nhưng tôi không biết về một cách.


Đã làm cho tôi! Cảm ơn.
Roberto Bonini

3

Trong magit , bạn có thể làm điều này với

l, =L

Sau đó, nó sẽ yêu cầu bạn cung cấp tệp và các dòng bắt đầu, kết thúc.

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.