Làm cách nào tôi có thể nhận được sự khác biệt giữa tất cả các cam kết xảy ra giữa hai ngày với Git?


116

Hay chỉ là tất cả các cam kết xảy ra giữa hai ngày? Trong SVN, bạn có thể làm một cái gì đó như

svn diff -r{date}:{date}

để làm điều đó! Tôi dường như không thể tìm thấy một Git tương đương với điều này.

Cụ thể tôi đang xem việc viết một kịch bản để gửi email hàng ngày với tất cả các mã được cam kết vào ngày hôm đó và bởi ai.

Câu trả lời:


159

Bạn đã có thể sử dụng git whatchanged --since="1 day ago" -p

Nó cũng có một --untilcuộc tranh luận.

Tài liệu


cảm ơn! Điều này đúng với những gì tôi muốn, nó thậm chí còn lấy tham số --committer, mặc dù điều đó không được liệt kê trong tài liệu của nó! Ngoài ra, 'git whatchanged' đã không xuất hiện trong 'git help'! Không biết tại sao ... cảm ơn lần nữa.
Chris

5
Bạn nên làm cho câu trả lời đã chọn của bạn để seth nhận được một số nghiệp.
Scott

18
@brbob Tôi biết điều này đã được trả lời từ lâu, nhưng chỉ dành cho người nào đó vấp phải điều này (như tôi đã làm) Git help nói: The command is kept primarily for historical reasons; fingers of many people who learned Git long before git log was invented by reading Linux kernel mailing list are trained to type it. Vì vậy, các tài liệu khuyến khích sử dụnggit log thay vì git whatchanged; lệnh cuối cùng này cũng sử dụng tùy chọn --no-merge của nhật ký git, vì vậy chúng cho kết quả tương tự.
Ramkes

2
git whatchanged là loại bí danh của lệnh git log theo tài liệu của git log
Vincent

2
git whatchangedkhông được chấp nhận kể từ phiên bản 2.21.0 mới nhất hiện tại. Tất cả những gì git whatchangedđạt được có thể đạt được git logvà nó chỉ được bảo tồn vì những lý do lịch sử. Xem chi tiết git-scm.com/docs/git-whatchanged/2.21.0
Devy

60

Các đề xuất trước đây có một số nhược điểm. Về cơ bản, tôi đang tìm kiếm một cái gì đó tương đương cvs diff -D"1 day ago" -D"2010-02-29 11:11". Trong khi thu thập ngày càng nhiều thông tin, tôi tìm thấy một giải pháp.

Những điều tôi đã thử:

  • git whatchanged --since="1 day ago" -ptừ đây

    Nhưng điều này mang lại sự khác biệt cho mỗi cam kết, ngay cả khi có nhiều cam kết trong một tệp. Tôi biết rằng "ngày" là một chút khái niệm lỏng lẻo trong git , tôi nghĩ rằng phải có một số cách để làm điều này.

  • git diff 'master@{1 day ago}..masterđưa ra một số cảnh báo warning: Log for 'master' only goes back to Tue, 16 Mar 2010 14:17:32 +0100.và không hiển thị tất cả các khác biệt.

  • git format-patch --since=yesterday --stdout không cho tôi bất cứ điều gì.

  • revs=$(git log --pretty="format:%H" --since="1 day ago");git diff $(echo "$revs"|tail -n1) $(echo "$revs"|head -n1) hoạt động bằng cách nào đó, nhưng có vẻ phức tạp và không giới hạn trong chi nhánh hiện tại.

Cuối cùng:

Vui thay, git-cvsserver không hỗ trợ "cvs diff -D" (không có nó được ghi lại ở đâu đó).


4
+1 cho git rev-list, đã đi một chặng đường dài để giải quyết vấn đề rất giống tôi đang gặp.
me_and

Đây không phải là câu trả lời được chấp nhận, seth's ngắn gọn và chính xác hơn.
ctford

6
@ctford, theo quan điểm của tôi, nó không đúng. Nó có thể báo cáo nhiều diff cho một tệp, không phải một diff cho mỗi tệp như svn / cvs diff.
Weidenrinde

1
@Weidenrinde +1, điều này thông minh hơn nhiều
rostamn739

1
Các git diff 'master@{1 day ago}..masterphương tiện cú pháp "kiểm tra reflog và con số ra nơi chi nhánh mastersử dụng để điểm trong kho lưu trữ tại địa phương 1 day ago ". Cụ thể, sẽ không sử dụng lịch sử cam kết thực tế của chi nhánh hiện tại master. Điều này rất hiếm khi điều bạn thực sự muốn.
Mikko Rantalainen

22

"ngày" là một chút khái niệm lỏng lẻo trong git. Một cam kết sẽ có một ngày tác giả có thể là một thời gian tốt trong quá khứ trước khi ai đó thực sự rút / cam kết vào kho lưu trữ của họ, đồng thời cam kết có thể bị từ chối và cập nhật để lên trên một cam kết rõ ràng mới hơn.

Một cam kết cũng có một ngày cam kết được cập nhật nếu một cam kết bị từ chối hoặc sửa đổi dưới bất kỳ hình thức nào. Các cam kết này có nhiều khả năng theo một thứ tự thời gian nào đó nhưng bạn vẫn cảm thấy xót xa cho người giao dịch có thời gian chính xác được đặt trên máy tính của mình và thậm chí, một cam kết không được sửa đổi có thể nằm trên một nhánh tính năng trên kho lưu trữ từ xa vô thời hạn trước đó được sáp nhập vào nhánh chính của một kho lưu trữ trung tâm.

Điều có lẽ hữu ích nhất cho mục đích của bạn là ngày giới thiệu trên kho lưu trữ cụ thể được đề cập. Nếu bạn đã bật reflog cho mỗi nhánh (xem git config core.logAllRefUpdates) thì bạn có thể sử dụngref@{date} cú pháp để chỉ vị trí của một nhánh tại một thời điểm cụ thể.

Ví dụ

git log -p master@{2009-07-01}..master@{now}

Bạn cũng có thể sử dụng các mô tả 'mờ' như:

git log -p "master@{1 month ago}..master@{yesterday}"

Các lệnh này sẽ hiển thị tất cả các xác nhận đã 'xuất hiện' trong nhánh đã cho của kho lưu trữ bất kể chúng thực sự bao nhiêu tuổi theo tác giả và ngày cam kết.

Lưu ý rằng reflog trên mỗi nhánh là dành riêng cho kho lưu trữ, vì vậy nếu bạn đang chạy lệnh log trên bản sao và bạn không kéo (giả sử) một tháng thì hãy rút tất cả các thay đổi cho tháng trước cùng một lúc, sau đó tất cả các thay đổi của tháng trước sẽ xuất hiện trong một @{1 hour ago}..@{now}phạm vi. Nếu bạn có thể chạy lệnh log trên kho lưu trữ 'trung tâm' mà mọi người đẩy tới, thì nó có thể làm những gì bạn muốn.


Viết rất tốt và trả lời tốt cho câu hỏi đã nêu ... nhưng tôi nghĩ nó sẽ không giúp ích nhiều cho việc thực hiện những gì brbob dự định.
Jakub Narębski

Nó phụ thuộc, nó có thể hữu ích nếu anh ta thực sự muốn phân tích những gì đã được đẩy đến một nhánh nhất định trên một kho lưu trữ trung tâm nhất định và lệnh log đã được chạy trên kho lưu trữ đó. Tôi nghĩ rằng một chỉnh sửa là theo thứ tự ...
CB Bailey

"Ngày cam kết được cập nhật nếu một cam kết bị từ chối hoặc sửa đổi theo bất kỳ cách nào", thực tế ngày đó không bao giờ thay đổi; toàn bộ cam kết được thay thế bằng một cam kết khác (mặc dù cây được cho là giống nhau).
hasen

2
@hasen j: Về mặt kỹ thuật, bạn đã đúng. Cam kết là bất biến. Khi bạn khởi động lại hoặc sửa đổi một cam kết và tạo một cam kết mới, thông điệp cam kết hiện tại, chi tiết về tác giả và ngày tác giả thường được sao chép từ cam kết cũ để giống như bạn đang cập nhật cam kết với id cam kết mới và ngày cam kết.
CB Bailey

Lưu ý rằng @{time spec}cú pháp luôn đề cập đến reflog cục bộ của bạn . Nó không đề cập đến lịch sử cam kết thực tế (DAG). Nếu bạn không hiểu rõ sự khác biệt, đừng sử dụng cú pháp này!
Mikko Rantalainen

14
git diff --stat @{2013-11-01}..@{2013-11-30}

hoặc là

git diff --stat @{2.weeks.ago}..@{last.week}

Điều này phụ thuộc vào reflog? Bởi vì nếu có, thì bạn thực sự không thể sử dụng điều này nếu repo bạn đang chạy lệnh này mới hơn (tức là nhân bản mới) so với lịch sử cam kết mà nó chứa.

2
Vâng, điều này hoàn toàn phụ thuộc vào reflog. Và vâng, điều này chỉ hoạt động trong lịch sử sao chép cục bộ, nhưng là một lệnh thuận tiện.
Aa.

1
Vâng, tôi chắc chắn đồng ý rằng nó thuận tiện, miễn là bạn đã từ chối các mục đủ cũ để hỗ trợ nó.

Cảm ơn bạn. Sử dụng câu trả lời của bạn, tôi đã có thể làm: git annotate --stat .. @ {2017-08-8} tên tệp | ít hơn; git annotate --stat .. @ {5.days.ago} tên tệp; để tôi có thể thấy những thay đổi trong bối cảnh.
Chris

Lưu ý rằng @{time spec}cú pháp luôn đề cập đến reflog cục bộ của bạn . Nó không đề cập đến lịch sử cam kết thực tế (DAG). Nếu bạn không hiểu rõ sự khác biệt, đừng sử dụng cú pháp này!
Mikko Rantalainen

4

Có lẽ

$ git format-patch --committer=<who> --since=yesterday --stdout

là những gì bạn muốn (có hoặc không có '--stdout')?


1
Câu hỏi nhanh, có phải - sử dụng ngày cam kết?
CB Bailey

3

Tôi tin rằng giải pháp chung là sử dụng:

git rev-list -n1 --first-parent --until=<a date string> <a ref>

Nếu không có - cha mẹ, bạn có thể nhận được một cam kết từ một chi nhánh mà sau đó được sáp nhập vào a refnhưng chưa được hợp nhất kể từa date string .

Đây là một cách thay thế bằng cách sử dụng --childrengrepthay vì -n1:

mlm_git_ref_as_of() {
    # # Examples #
    #
    # Show all commits between two dates:
    #
    #     git log $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    #
    # Show diffs of all commits between two dates:
    #
    #     git diff $(mlm_git_ref_as_of '2012-05-21 09:00:00-0400')..$(mlm_git_ref_as_of '2012-05-21 17:00:00-0400')
    local as_of="$1"
    local ref="${2:-HEAD}"
    # Get the most recent commit (--children, grep -v ' ') that was on
    # the given branch ($ref, --first-parent) as of a given date
    # ($as_of)
    git rev-list --children --first-parent --until="$as_of" "$ref" | grep -v ' '
}

Tôi không quen thuộc git whatchangedtrước khi đọc Q & A này, nhưng nó mang lại kết quả rất khác cho tôi, vì vậy tôi không chắc nó đang làm gì.


3

Một cách đơn giản khác mà bạn có thể nhận được khác biệt của tất cả các thay đổi kể từ một ngày nhất định là chỉ cần tìm cam kết đầu tiên Xxảy ra vào hoặc sau ngày đó, sau đó sử dụng

git diff X

Điều này có lợi thế là nó không phụ thuộc vào các mục nhập lại trong một bản sao mới, không giống như

git diff <reference>@{n}..
git log <reference>@{n}..

giải pháp trong


2

Đây là nhiều hơn một câu trả lời hài hước, bởi vì có khả năng là một cách tốt hơn. Điều này sẽ hiển thị tất cả các băm cam kết cho ngày hôm nay.

git log --pretty="format:%H %ai" | grep `date +"%Y-%m-%d"` | awk {'print $1'}`

; ·)


2

Bạn cũng có thể sử dụng git-format-patch để chuẩn bị các bản vá (diffs) và gửi chúng qua email.

Sử dụng các tùy chọn [kể từ] hoặc [phạm vi sửa đổi] để chỉ định phạm vi cam kết.


2

Để xem các tệp Git thay đổi từ ngày này sang ngày khác trên chi nhánh của bạn, hãy sử dụng công thức sau:

  1. kiểm tra chi nhánh của bạn.
  2. kéo và cập nhật các thay đổi từ kho lưu trữ từ xa
  3. xem các tập tin khác nhau từ phạm vi ngày đến phạm vi ngày

Công thức :

git checkout <branch>
git pull
git diff --stat @{fromDate}..@a{toDate}

Hãy chú ý rằng ngày tháng ở định dạng YYYY-MM-DD :

git diff --stat @{2019-08-20}..@a{2019-08-21}

Nếu bạn muốn quan sát các thay đổi trên tệp cụ thể trong khoảng thời gian cụ thể (xem mã khác), chỉ cần điều hướng tệp hiện tại:

Ví dụ :

git diff @{2019-01-01}..@{2019-01-02} ~/dev/myApp/package.json

0

Tôi sẽ làm theo cách tôi làm: git logtrong một ngày sẽ cho bạn cam kết băm cho chi nhánh hiện tại. Sau đó, tôi chỉ sử dụng một cái gì đó giống như git diff 8fgdfg8..565k4l5mang lại cho tôi sự khác biệt thích hợp được tổng hợp bởi các tập tin. Hy vọng điều này sẽ giúp, không được thử nghiệm nhiều mặc dù

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.