2010-06-04 31 views
103

Có ý nghĩa khi thực hiện git rebase trong khi vẫn giữ dấu thời gian cam kết không?git rebase mà không thay đổi dấu thời gian cam kết

Tôi tin rằng hậu quả là chi nhánh mới sẽ không nhất thiết phải có ngày tháng theo thứ tự thời gian. Có phải đó là tất cả về mặt lý thuyết có thể là tất cả không? (ví dụ: sử dụng lệnh đường ống dẫn nước; chỉ tò mò ở đây)

Nếu về lý thuyết, có thể thực hành với rebase, không thay đổi dấu thời gian không?

Ví dụ, giả sử tôi có cây sau:

master <jun 2010> 
    | 
    : 
    : 
    :  oldbranch <feb 1984> 
    : /
oldcommit <jan 1984> 

Bây giờ, nếu tôi rebase oldbranch trên master, ngày của những thay đổi cam kết từ tháng 2 năm 1984 đến tháng sáu năm 2010. Có thể thay đổi hành vi sao cho dấu thời gian cam kết không bị thay đổi? Cuối cùng, tôi sẽ có được:

 oldbranch <feb 1984> 
    /
master <jun 2010> 
    | 
    : 

Điều đó có hợp lý không? Thậm chí nó có được cho phép trong git có một lịch sử mà một cam kết cũ có một cam kết gần đây hơn với tư cách là một phụ huynh không?

+2

Thật thú vị khi câu trả lời cho câu hỏi thực sự là "bạn không cần phải làm gì cả - đó là cách hoạt động được mặc định". Nhưng bây giờ giả sử bạn muốn cam kết được sắp xếp theo thứ tự ngày thích hợp trong khi thực hiện rebase (đó là kịch bản khá tự nhiên nếu bạn nghĩ về nó). Bây giờ, tôi đã không thể tìm thấy làm thế nào để đạt được điều đó, và đăng q của tôi là http://stackoverflow.com/questions/12270357/really-flatten-a-git-merge – pfalcon

+1

David đề cập đến một tùy chọn khác để đặt lại ngày bắt đầu: 'git rebase --committer-date-là-author-date SHA'. Xem [câu trả lời đã chỉnh sửa của tôi dưới đây] (http://stackoverflow.com/a/2976598/6309) – VonC

+0

Tôi vừa viết một [câu trả lời mở rộng] (http://stackoverflow.com/a/30819930/4265352) trên [tương tự câu hỏi] (http://stackoverflow.com/q/30790645/4265352) mà tác giả đã thử các câu trả lời được giải thích ở đây và không thể áp dụng chúng một cách thỏa đáng. – axiac

Trả lời

27

Một câu hỏi quan trọng của Von C giúp tôi hiểu những gì đang xảy ra: khi rebase bạn, thay đổi dấu thời gian các committer, nhưng không phải là tác giả dấu thời gian, mà đột nhiên tất cả có ý nghĩa. Vì vậy, câu hỏi của tôi thực sự không đủ chính xác.

Câu trả lời là việc rebase thực sự không thay đổi dấu thời gian của tác giả (bạn không cần phải làm bất kỳ điều gì cho điều đó), điều đó phù hợp với tôi một cách hoàn hảo.

+1

+1 - Tôi có một bí danh git tại chỗ (https://coderwall.com/p/euwpig/a-better-git-log) mà rõ ràng sử dụng dấu thời gian của người đi làm, điều này gây nhầm lẫn tôi. Gitk và git log đều hiển thị dấu thời gian của tác giả. – 1615903

102

Cập nhật tháng 6 năm 2014: David Fraser đề cập in the comments một giải pháp cũng nêu chi tiết trong "Change timestamps while rebasing git branch", sử dụng tùy chọn --committer-date-is-author-date (giới thiệu ban đầu trong tháng 1 năm 2009 trong commit 3f01ad6

Lưu ý rằng tùy chọn --committer-date-is-author-date dường như rời khỏi timestamp tác giả và đặt dấu thời gian của dấu cộng là giống như dấu thời gian của tác giả gốc, đó là những gì mà OP Olivier Verdier muốn.

Tôi đã tìm thấy cam kết cuối cùng với ngày chính xác và đã làm:

git rebase --committer-date-is-author-date SHA 

Xem git am:

--committer-date-is-author-date 

Theo mặc định, lệnh ghi ngày từ tin nhắn e-mail như các cam kết ngày tác giả, và sử dụng thời điểm cam kết tạo như ngày committer .
Điều này cho phép người dùng nói dối về ngày bắt đầu bằng cách sử dụng cùng một giá trị với ngày tác giả.


(câu trả lời gốc, June 2012)

Bạn có thể thử, đối với một không tương tác rebase

git rebase --ignore-date 

(từ này SO answer)

Đây là được chuyển đến git am, đề cập:

--ignore-date 

Theo mặc định, lệnh ghi ngày từ tin nhắn e-mail như các cam kết ngày tác giả, và sử dụng thời điểm cam kết tạo như ngày committer.
Điều này cho phép người dùng nói dối về ngày tác giả bằng cách sử dụng cùng một giá trị với ngày của người cam kết.

Đối với git rebase, tùy chọn này là "Không tương thích với tùy chọn - tương tác".

Kể từ you can change at will the timestamp of old commit date (với git filter-branch), tôi cho rằng bạn có thể tổ chức lịch sử Git của bạn với bất kỳ thứ tự ngày cam kết nào bạn muốn/cần, ngay cả set it to the future!.


Như Olivier đề cập trong câu hỏi của anh, ngày tác giả không bao giờ thay đổi bởi một rebase;
Từ Pro Git Book:

  • Tác giả là người đầu viết tác phẩm,
  • trong khi có duyên là người cuối cùng áp dụng công việc.

Vì vậy, nếu bạn gửi bản vá cho dự án và một trong những thành viên cốt lõi áp dụng bản vá, cả hai bạn đều nhận được tín dụng.

Để có thêm rõ ràng, trong trường hợp này, như Olivier nhận xét:

các --ignore-date làm ngược lại những gì tôi đã cố gắng để đạt được!
Cụ thể, nó sẽ xóa dấu thời gian của tác giả và thay thế chúng bằng dấu thời gian cam kết!
Vì vậy, câu trả lời đúng cho câu hỏi của tôi là:
Không làm bất cứ điều gì, vì git rebase thực sự không thay đổi dấu thời gian của tác giả theo mặc định.


+0

Thú vị về những ngày tùy ý để cam kết. Tuy nhiên, 'git rebase --ignore-date' không hoạt động. Nó thay đổi ngày của các cam kết rebased. –

+0

@Olivier: lạ: bạn đã thực hiện một rebase * non * -interactive chưa? Và giữa Ngày tác giả và Ngày chuyển nhượng, chúng tôi có chắc chắn theo dõi ngày "đúng" không? – VonC

+1

Cảm ơn VonC, sự khác biệt giữa dấu thời gian của tác giả và người đi làm, đó là điều làm cho nó đột nhiên rõ ràng. Tôi đã viết câu trả lời cho câu hỏi của tôi trong bài viết của tôi, nhưng cảm thấy tự do để thích ứng với câu trả lời của bạn để phản ánh điều đó. –

104

Nếu bạn đã hơi say lên cam kết ngày (có lẽ với một rebase) và muốn đặt lại chúng vào ngày tác giả tương ứng của họ, bạn có thể chạy:

git filter-branch --env-filter 'GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; export GIT_COMMITTER_DATE'

+1

Tôi vừa thử điều này, nhưng không có hiệu lực. Tôi nhận được kết quả đầu ra: 'CẢNH BÁO: Ref 'refs/heads/master' không thay đổi'. Tôi đang sử dụng git phiên bản 1.7.9.5 trên Linux (64 bit) –

+13

Tôi muốn thêm một cách tiếp cận khác nếu bạn đã sửa lỗi nhưng không muốn lặp lại thông qua toàn bộ lịch sử: 'git rebase --committer- date-is-author-date ' Bằng cách này, git sẽ đặt lại ngày cam kết chỉ cho các cam kết được áp dụng khi (có thể là cùng một tên chi nhánh bạn đã sử dụng khi bạn vặn lên). – speakman

+0

Câu trả lời được chấp nhận không hoạt động trong năm 2016, nhưng câu trả lời của @ speakman đã làm! –

10

Theo mặc định, git rebase sẽ đặt dấu thời gian của người ký phát vào thời điểm khi cam kết mới được tạo ra, nhưng giữ nguyên dấu thời gian của tác giả. Hầu hết thời gian, đây là hành vi mong muốn, nhưng tại một số trường hợp, chúng tôi không muốn thay đổi dấu thời gian của dấu cộng. Làm thế nào chúng ta có thể đạt được điều đó? Vâng, đây là mẹo tôi thường làm.

Trước tiên, hãy đảm bảo mỗi cam kết bạn sắp sửa có một thông báo cam kết và dấu thời gian tác giả duy nhất (Đây là mẹo cần cải tiến, hiện tại nó phù hợp với nhu cầu của tôi).

Trước khi khởi động lại, hãy ghi dấu thời gian của người gửi, dấu thời gian của tác giả và thông báo cam kết của tất cả các cam kết sẽ được xóa lại thành tệp.

#NOTE: BASE is the commit where your rebase begins 
git log --pretty='%ct %at %s' BASE..HEAD > hashlog 

Sau đó, hãy thực hiện việc rebase thực tế.

Cuối cùng, chúng tôi thay thế dấu thời gian của người gửi hiện tại bằng dấu thời gian được ghi trong tệp nếu thông báo cam kết giống nhau bằng cách sử dụng git filter-branch.

git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%at %s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_COMMITTER_DATE=$__date || cat' 

Nếu họ gặp khó khăn, chỉ cần kiểm git reflog hoặc tất cả các refs/original/ refs.

Furthormore, bạn có thể làm điều tương tự với dấu thời gian của tác giả. Ví dụ: nếu dấu thời gian của một số cam kết của tác giả không đúng thứ tự và mà không sắp xếp lại các cam kết này, chúng tôi chỉ muốn dấu thời gian của tác giả hiển thị theo thứ tự , sau đó các lệnh sau sẽ hữu ích.

git log --pretty='%at %s' COMMIT1..COMMIT2 > hashlog 
join -1 1 -2 1 <(cat hashlog | cut -f 1 | sort -nr | awk '{ print NR" "$1 }') <(cat hashlog | awk '{ print NR" "$0 }') | cut -d" " -f2,4- > hashlog_ 
mv hashlog_ hashlog 
git filter-branch --env-filter '__date=$(__log=$(git log -1 --pretty="%s" $GIT_COMMIT); grep -m 1 "$__log" ../../hashlog | cut -d" " -f1); test -n "$__date" && export GIT_AUTHOR_DATE=$__date || cat' 
+0

Đây là một mẹo tuyệt vời! Nó cho phép tôi chỉ viết lại 75 cam kết thay vì 1100+ từ việc sử dụng các câu trả lời khác. – audun

+0

Điều này thật tuyệt vời! Có cách nào để sửa đổi kịch bản để bảo vệ người bắt đầu ban đầu không? –

+0

@DavidDeMar nên, giống nhau, chỉ cần thay đổi nhật ký git --khá để ghi lại email gốc và sửa đổi tập lệnh tương ứng. – weynhamz

Các vấn đề liên quan