taahhüt zaman damgalarını değiştirmeden git rebase


157

git rebaseİşlem zaman damgalarını korurken performans göstermek mantıklı olur mu?

Bir sonucun yeni şubenin kronolojik olarak kesin tarihlere sahip olmayacağına inanıyorum. Bu teorik olarak mümkün mü? (örneğin sıhhi tesisat komutlarını kullanarak; sadece burada merak ediyorum)

Teorik olarak mümkünse, zaman damgalarını değiştirmek değil, rebase ile pratikte mümkün müdür?

Örneğin, aşağıdaki ağacın olduğunu varsayalım:

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

Ben rebase Şimdi, eğer oldbranchüzerinde master, tarihi mümkün mü damgası değişmez taahhüt böylece o davranışı değiştirmek için jun 2010 için Şubat 1984 değişiklikleri taahhüt? Sonunda böylece elde:

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

Bu hiç mantıklı mı? Git'te eski bir taahhüdün ebeveyn olarak daha yeni bir taahhüde sahip olduğu bir geçmişe sahip olmasına bile izin verilir mi?


3
Sorunun cevabının gerçekten de "hiçbir şey yapmanıza gerek yok - varsayılan olarak bu şekilde çalışması" korkak. Ancak şimdi, rebase yaparken taahhüdün uygun tarih sırasına göre sıralanmasını istediğinizi varsayalım (bu düşünürseniz oldukça doğal bir senaryodur). Şimdi, bunu nasıl başaracağımı bulamadım ve
q'umu

1
David committer tarihini sıfırlamak için başka bir seçenek bahseder: git rebase --committer-date-is-author-date SHA. Bkz aşağıda benim Düzenlenen cevabı
VonC

Yazarı burada açıklanan cevapları deneyen ve bunları tatmin edici bir şekilde uygulayamayan benzer bir soru üzerine kapsamlı bir cevap yazdım .
axiac

Yanıtlar:


149

Güncelleme Haziran 2014: David Fraser bahseder yorumlarda bir çözüm de ayrıntılı " Değişim git şube rebasing ederken damgalarının seçeneğini kullanarak," --committer-date-is-author-dateiçinde Ocak 2009 başlanabilir ( 3f01ad6 işlemek

O Not --committer-date-is-author-dateseçeneği yazar damgası bırakın ve ne orijinal yazar zaman damgası, aynı olacak şekilde committer damgası ayarlamak gibi görünüyor OP Olivier Verdier istedi.

Son sözü doğru tarihte buldum ve yaptım:

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

Bkz git am:

--committer-date-is-author-date

Varsayılan olarak komut, e-posta iletisindeki tarihi taahhüt yazarı tarihi olarak kaydeder ve taahhüt oluşturma saatini başlangıç ​​tarihi olarak kullanır.
Bu, kullanıcının yazar tarihiyle aynı değeri kullanarak değişiklik tarihi hakkında yalan söylemesini sağlar .


(Orijinal cevap, Haziran 2012)

Etkileşimli olmayan bir rebase için deneyebilirsiniz

git rebase --ignore-date

(bu SO cevabından )

Bu git am, şu sözlerden geçmektedir:

 --ignore-date

Varsayılan olarak komut, e-posta iletisindeki tarihi taahhüt yazarı tarihi olarak kaydeder ve taahhüt oluşturma saatini başlangıç ​​tarihi olarak kullanır.
Bu, kullanıcının değişme tarihiyle aynı değeri kullanarak yazarın tarihi hakkında yalan söylemesini sağlar.

Çünkü git rebase, bu seçenek "--ingrative seçenekle uyumsuz."

Beri eski senden damgası tarihini işlemek olacak değiştirebileceği (ile git filter-branch), ben bile, istediğiniz tarih sırası / ihtiyacını işlemek ne olursa olsun ile Git geçmişini düzenleyebilir varsayalım geleceğe ayarlayın! .


As Olivier onun söz konusu bahseder, yazar tarih bir rebase tarafından değiştirilen hiçbir zaman;
Gönderen Pro Git Kitabı :

  • Yazar, eseri ilk olarak yazan kişidir,
  • oysa taşıt, işi en son uygulayan kişidir.

Yani, bir projeye yama gönderirseniz ve çekirdek üyelerden biri yamayı uygularsa, ikiniz de kredi alırsınız.

Bu örnekte, Olivier'in belirttiği gibi daha açık olmak gerekirse:

--ignore-dateBen başarmak için çalışıyordu tersini yapar !
Yani, yazarın zaman damgasını siler ve yerine zaman damgasını koyar!
Yani sorumun doğru cevabı:
Hiçbir şey yapmayın, çünkü git rebase aslında yazarların zaman damgalarını varsayılan olarak değiştirmez.



1
Taahhüt edilecek keyfi tarihler hakkında ilginç. Ancak, git rebase --ignore-dateçalışmıyor. Yeniden temel alınan taahhütlerin tarihlerini değiştirir.
Olivier Verdier

@Olivier: garip: etkileşimli olmayan bir rebase yaptınız mı? Ve Yazar Tarihi ile Tebliğ Tarihi arasında, "doğru" tarihi izlediğimizden emin miyiz?
VonC

1
Teşekkürler VonC, yazar ve komünist zaman damgası arasındaki fark, bu her şeyi birden açıkça ortaya koyuyor. Sorumun cevabını yazımda yazdım, ancak cevabınızı bunu yansıtacak şekilde uyarlamaktan çekinmeyin.
Olivier Verdier

4
: Daha hassas olması için --ignore-dateyapar tersini elde etmek ne çalışıyordum! Yani, yazarın zaman damgasını siler ve yerine zaman damgasını koyar! Yani sorumun doğru cevabı: hiçbir şey yapmayın, çünkü git rebasevarsayılan olarak yazarların zaman damgalarını değiştirmez.
Olivier Verdier

5
O Not --committer-date-is-author-dateseçeneği ... yazar damgası bırakın ve Olivier istediğim şey orijinal yazar zaman damgası, aynı olacak şekilde committer damgası ayarlamak gibi görünüyor
David Fraser

118

Teslim tarihlerini (belki de bir rebase ile) zaten mahvettiyseniz ve bunları ilgili yazar tarihlerine sıfırlamak istiyorsanız, şunları yapabilirsiniz:

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


1
Sadece denedim, ama bir etkisi yok. Ben folowing çıktı var: WARNING: Ref 'refs/heads/master' is unchanged. Linux (64 bit) üzerinde git 1.7.9.5 sürümünü kullanıyorum
Markus N.

20
Zaten berbat ettiyseniz ancak tüm geçmiş boyunca yineleme yapmak istemiyorsanız başka bir yaklaşım eklemek istiyorum: git rebase --committer-date-is-author-date <base_branch> Bu şekilde git, bitiş tarihini yalnızca <base_branch> üzerine uygulanan taahhütler için sıfırlayacaktır (muhtemelen vidaladığınızda kullandığınız aynı dal adı).
speakman

Kabul edilen cevap 2016'da işe yaramadı, ancak @ speakman'ın cevabı işe yaradı!
Theodore R. Smith

2
@ speakman'ın cevabı Ekim 2016'da işe yaramadı, ama Andy yaptı!
Amedee Van Gasse

2
Bu Windows üzerinde çalışmaz. Windows Bash kullanarak çalışabildim.
vaindil

33

Von C lik bir önemli soru bana neler olduğunu anlamaya yardımcı: zaman Rebase, Committer damgası değişiklikleri, ancak yazarın aniden tüm mantıklı zaman damgası. Yani sorum aslında yeterince kesin değildi.

Cevap, rebase aslında yazarın zaman damgalarını değiştirmez (bunun için hiçbir şey yapmanıza gerek yoktur), bu bana mükemmel bir şekilde uyuyor.


3
+1 - Yerde git takma adım var ( coderwall.com/p/euwpig/a-better-git-log ) görünüşe göre beni şaşırtan komşunun zaman damgasını kullanıyor. Gitk ve git günlüğünün her ikisi de yazarın zaman damgasını gösterir.
1615903

15

Git rebase varsayılan olarak, yolvericinin zaman damgasını yeni taahhüdün oluşturulduğu zamana ayarlar, ancak yazarın zaman damgasını olduğu gibi bırakır. Çoğu zaman, bu istenen davranıştır, ancak bazı senaryolarda, komitenin zaman damgasını da değiştirmek istemiyoruz. Bunu nasıl başarabiliriz? İşte genelde yaptığım hileler.

Öncelikle, yeniden oluşturmak üzere olduğunuz taahhütlerin her birinin benzersiz bir taahhüt mesajı ve yazar zaman damgası olduğundan emin olun (Bu, hile iyileştirmeleri gereken, şu anda ihtiyaçlarıma uygun).

Rebase'den önce, bir dosyaya yeniden baslanacak tüm taahhütlerin komisyon sahibinin zaman damgasını, yazarın zaman damgasını ve taahhüt mesajını kaydedin.

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

Ardından, gerçek rebase gerçekleşsin.

Son olarak, yürütme mesajı aynı ise, geçerli iletmenin zaman damgasını dosyada kayıtlı olanla değiştiririz 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'

Bir şeyler ters giderse, yalnızca ödeme git reflogveya tüm refs/original/referanslar.

Dahası, yazarın zaman damgasına benzer bir şey yapabilirsiniz.

Örneğin, yazarın bazı taahhütlerin zaman damgası bozuksa ve bu taahhütleri yeniden düzenlemeden, yazarın zaman damgasının sırayla gösterilmesini istiyoruz, o zaman aşağıdaki komutlar yardımcı olacaktır.

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'

Bu harika bir numara! Diğer cevapları kullanmaktan 1100+ yerine sadece 75 komisyon yazmamı sağladı.
audun

Bu fantastik! Orijinal değiştiriciyi de korumak için betiği değiştirmenin bir yolu var mı?
David DeMar

@DavidDeMar aynı, sadece orijinal e-postayı kaydetmek için git logunu değiştirmeli ve betiği buna göre değiştirmelidir.
weynhamz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.