Có cách nào trong git để có được ngày đẩy cho một cam kết nhất định không?


91

Tôi đang tự hỏi liệu có cách nào để xem ngày đẩy được liên kết với từng cam kết trong nhật ký git không. Nếu điều đó là không thể, có cách nào để xem tất cả các cam kết theo một sự thúc đẩy nhất định.

Tôi đang viết một chương trình cần theo dõi các cam kết khi chúng được đẩy. Bởi vì nhật ký git được sắp xếp theo ngày cam kết, không phải ngày đẩy, tôi không thể xem các cam kết gần đây nhất được đẩy. Ví dụ: nếu người dùng cam kết đến kho lưu trữ cục bộ của anh ta 2 ngày trước khi anh ta đẩy lên kho chính, thì cam kết đó sẽ được đặt sau 2 ngày so với các cam kết khác trong nhật ký kho lưu trữ chính.

Câu trả lời:


77

Tôi đã mất một thời gian dài để thu thập thông tin rải rác và cuối cùng tìm ra câu trả lời tốt nhất cho câu hỏi này, nhưng bây giờ tôi biết mình đã có nó. Chỉ trong hai dòng, không có mã và không có móc:

# required for a bare repo
git config core.logAllRefUpdates true

git reflog --date=local master

Đơn giản cuối cùng.

Cảnh báo: bạn có thể muốn ghi đè các giá trị mặc định của gc.reflogExpiregc.reflogExpireUnreachable. Kiểm tra git help reflogchi tiết và hiểu cách thức và lý do điều này hoạt động.

Hai lệnh trên phải được chạy bên trong bản sao mà bạn đẩy đến . Nếu điều đó là không thể thì một phép ước lượng phải chạy trong một bản sao vĩnh viễn khác :

git fetch               origin        # often and *regularly*
git reflog --date=local origin/master

Không bao giờ xóa bản sao vĩnh viễn này nếu không bạn sẽ mất ngày tháng.


2
Tôi muốn thêm rằng trong trường hợp của tôi, tôi phải làm git reflog --date=local origin/master(lưu ý origin/) để xem danh sách các lần đẩy. Nếu không, chỉ có cam kết, kiểm tra và kéo mới có trong danh sách (điều này cũng hữu ích). Trên thực tế, tôi đã được chỉ ra nó bởi câu trả lời của @ JonathanDay .
NIA

@NIA: origin / master sẽ chỉ cung cấp cho bạn giá trị gần đúng. Tôi đã cập nhật câu trả lời của mình sau bình luận của bạn, điều này có làm rõ không?
MarcH

37

Git là một hệ thống kiểm soát phiên bản phân tán, vì vậy bạn phải xác định cẩn thận "ngày đẩy" nghĩa là gì. Ví dụ: giả sử người dùng A đẩy một số cam kết vào kho lưu trữ của người dùng B. Một lúc sau, người dùng B đẩy những cam kết tương tự đó vào kho lưu trữ thứ ba. Bạn quan tâm đến ngày nào?

Tôi đang suy đoán rằng bạn có một kho lưu trữ được chia sẻ và muốn người dùng của kho lưu trữ được chia sẻ đó có thể xác định thời điểm một cái gì đó được xuất bản lên kho lưu trữ. Nếu điều đó đúng, bạn sẽ phải thu thập thông tin đó trong kho lưu trữ được chia sẻ.

Các tin xấu

Thật không may, không có cách nào để thêm ngày vào các thông báo cam kết. Điều đó sẽ thay đổi ID cam kết (là hàm băm SHA1 của nội dung), gây ra tất cả các loại vấn đề.

Tin tốt

May mắn thay, Git có một tính năng (tương đối mới) được gọi là ghi chú . Tính năng này cho phép bạn đính kèm văn bản tùy ý vào các cam kết, git logcó thể hiển thị. Ghi chú có thể được chỉnh sửa và chia sẻ với những người khác.

Bạn có thể sử dụng tính năng ghi chú để đính kèm thông báo "cam kết này đã được nhận vào [ngày]" vào mỗi cam kết khi nó được nhận bởi kho lưu trữ được chia sẻ.

Xem git help notesđể biết chi tiết.

Cách ghi ngày

Đây là cách tiếp cận tôi khuyên bạn nên:

  1. Sửa đổi post-receivehook trên kho lưu trữ được chia sẻ của bạn để hướng dẫn từng cam kết mới có thể truy cập cho mỗi tham chiếu được cập nhật.
  2. Đối với mỗi cam kết, hãy thêm một cái gì đó như "[người dùng] của [repository_url] đã thêm cam kết này vào [ref] vào [date]" vào ghi chú của cam kết.

    Bạn có thể muốn sử dụng một tham chiếu ghi chú dành riêng cho mục đích này (như refs/notes/received-on) thay vì mặc định refs/notes/commits. Điều này sẽ ngăn chặn xung đột với các ghi chú được tạo cho các mục đích khác.

  3. Sửa đổi receivehook của bạn để từ chối cập nhật đối với tham chiếu ghi chú của bạn (để ngăn người dùng vô tình hoặc cố ý làm rối các ghi chú).
  4. Yêu cầu tất cả người dùng chạy các lệnh sau từ bên trong cây làm việc của họ:

    # Fetch all notes from the shared repository.
    # Assumes the shared repository remote is named 'origin'.
    git config --add remote.origin.fetch '+refs/notes/*:refs/remote-notes/origin/*'
    
    # Show all notes from the shared repository when running 'git log'
    git config --add notes.displayRef 'refs/remote-notes/origin/*'
    

    Bước này là cần thiết vì Git bỏ qua các tham chiếu không phải nhánh, không phải thẻ trong kho lưu trữ ngược dòng theo mặc định.

Ở trên giả định rằng các tham chiếu chỉ là nâng cao, không bao giờ bị xóa hoặc buộc cập nhật. Có thể bạn sẽ muốn post-receivehook cũng thêm ghi chú "đã xóa vào [date]" để xử lý những trường hợp này.


Tôi đã sử dụng ý tưởng của bạn trong blog của tôi mnaoumov.wordpress.com/2013/01/31/git-get-push-date
mnaoumov

7
git reflog show origin/master --pretty='%h %gd %gs %s' --date=iso

Điều này dường như hoạt động khá tốt đối với tôi. Ngày cam kết (% cd) gây hiểu lầm vì nó không nhất thiết phải giống với ngày đẩy. Tuy nhiên, tùy chọn --date = iso sẽ xuất ra ngày đẩy / tìm nạp .

Lưu ý, nếu bạn đã tìm nạp từ origin / master, nó sẽ in ra ngày bạn tìm nạp; KHÔNG PHẢI là ngày mà người khác đẩy cam kết.

 - %h:  abrev. hash
 - %gd: human readable reflog selector
 - %gs: reflog subject
 - %s:  subject/commit message

Phần thưởng: Tất nhiên, bạn có thể thực hiện nhiều định dạng đẹp hơn. Cho đến nay, tôi thích mã màu này. Tuy nhiên, nó hơi nhiều để gõ. Điều này sẽ xuất ra SHA thành màu đỏ, bộ chọn reflog thành màu lục lam và reflog đối với màu xanh lục.

git reflog show origin/master --pretty='format:%C(red)%h%Creset %C(cyan)%gd%Creset %C(green)%gs%Creset: %s' --date=iso

Xin chào VC có nghĩa là nếu đầu ra của lệnh "reflog show origin / master --pretty = '% Cred% h% Creset -% C (yellow)% gd% Creset% Cblue (% gs)% Creset% s' - -date = iso "is" da4c192cd -origin / master @ {2019-02-07 08:13:40 +0100} (pull: tua nhanh) JIRA-2542 báo cáo kiểm tra nâng cao ", điều đó có nghĩa là nội dung của JIRA chi nhánh của tôi -2542 đã được hợp nhất trên origin / master thông qua một màn trình diễn nhanh vào lúc 2019-02-07 08:13:40?
Simon

Chào Simon, vâng. Bạn đã thực hiện kéo git trên chi nhánh của mình và nó được hợp nhất trên origin / master thông qua tua nhanh tại thời điểm đó.
VC

Nó chỉ hoạt động trên kho của tác giả. Nếu tôi sao chép kho lưu trữ, giá trị sẽ trống. Bạn không thể xem thời gian đẩy của người khác.
ramwin

6

Hãy nhìn vào git reflog show master. Có thể không phải là định dạng chính xác mà bạn muốn, nhưng sẽ chỉ cho bạn đúng hướng.

Một ý tưởng khác là chạy một script bên trong một push hook.


Tôi đã nghĩ đến việc chạy push hook, nhưng có vẻ như đó phải là nỗ lực cuối cùng. Với một hook, có vẻ như mọi người dùng sẽ phải có hook đó trong mỗi kho của họ. Bạn có thể được cụ thể hơn về git reflog show master? Tôi muốn có thể xem ngày đẩy của mỗi cam kết cá nhân của người dùng.
justkikuchi

git reflog hiển thị thứ tự thay đổi trong bất kỳ repo nào bạn chạy nó. Tôi không chắc liệu có cách trực tiếp để lấy ngày hay không, nhưng trong .git/logs/refs/heads/masterđó hiển thị một dấu thời gian.
Karl Bielefeldt

3
Đối với hooks, có hook nhận chạy trên máy bạn đẩy đến . Vì việc đẩy chỉ liên quan đến một repo cụ thể, tôi cho rằng bạn có một repo "may mắn" nhất định mà bạn muốn chạy nó. Tương tự đối git reflogvới vấn đề đó.
Karl Bielefeldt

5

Câu trả lời này liên quan đến việc kiểm tra nhật ký lại trên điều khiển từ xa có thể hữu ích ( https://stackoverflow.com/a/8791295/336905 ) bằng cách cung cấp cho bạn thông tin mà một nhánh đã được đẩy ngay cả khi nó không hiển thị cam kết nào đã được đẩy, nhưng bạn có thể tương quan chéo bằng cách tìm lần thúc đẩy tiếp theo sau ngày cam kết cục bộ. Không dễ bị đánh lừa, nhưng hữu ích nếu bạn chưa triển khai đề xuất ghi chú tuyệt vời từ @RichardHansen đã đăng trước đó


1
Với một lưu ý rằng reflog of origin/branchsẽ chỉ hiển thị những thay đổi được thực hiện trên máy hiện tại , điều này cực kỳ hữu ích! Để sử dụng hàng ngày, tôi không muốn triển khai bất kỳ hook nào, vì vậy đối với một câu hỏi đơn giản "Hmmm, khi tôi push commit đó vào tuần trước?" - nó hoạt động tốt.
NIA

4

Bạn cũng có thể xem thời gian sửa đổi tệp của tệp đối tượng cam kết trong thư mục "đối tượng" trong kho lưu trữ git trên chính máy chủ.


2

Tại sao git AuthorDate khác với commitDate?

  • AuthorDate là khi cam kết được tạo lần đầu tiên.
  • CommitDate là khi cam kết được sửa đổi lần cuối (ví dụ: rebase).

Bạn có thể lấy những cái đó bằng các --prettytùy chọn định dạng:

       o    %cd: committer date
       o    %cD: committer date, RFC2822 style
       o    %cr: committer date, relative
       o    %ct: committer date, UNIX timestamp
       o    %ci: committer date, ISO 8601 format

Vì vậy, nếu bạn và các nhà phát triển khác đang làm git rebasetrước đó git push, bạn sẽ có ngày cam kết muộn hơn ngày tác giả .

Lệnh này hiển thị ngày cam kết: git log --pretty=fuller


1

Tôi đoán bạn có thể sử dụng ký hiệu tiếp theo để lấy ngày đẩy: git log -g --date = local

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.