Git'teki eski bir taahhüdün zaman damgasını nasıl değiştirebilirim?


747

Cevapları Nasıl Yapılır mevcut, unpushed kaydedilmesini değiştirmek için? henüz yukarı doğru itilmemiş olan önceki taahhüt mesajlarını değiştirmenin bir yolunu tanımlayın. Yeni mesajlar, orijinal taahhütlerin zaman damgalarını devralır. Bu mantıklı görünüyor, ancak zamanları yeniden ayarlamanın bir yolu var mı?



34
git commit --amend --reset-author
Erick M. Sprengel

Yanıtlar:


535

Kullanım git filter-branchbir env filtreli setleri olduğunu GIT_AUTHOR_DATEve GIT_COMMITTER_DATEtaahhüt belirli karma için size düzeltme arıyoruz.

Bu, bunu ve gelecekteki tüm karmaları geçersiz kılacaktır.

Misal:

Taahhüt tarihlerini değiştirmek 119f9ecf58069b265ab22f1f97d2b648faf932e0isterseniz, böyle bir şeyle yapabilirsiniz:

git filter-branch --env-filter \
    'if [ $GIT_COMMIT = 119f9ecf58069b265ab22f1f97d2b648faf932e0 ]
     then
         export GIT_AUTHOR_DATE="Fri Jan 2 21:38:53 2009 -0800"
         export GIT_COMMITTER_DATE="Sat May 19 01:01:01 2007 -0700"
     fi'


8
Bu doğru değeri buldu , ancak bu değişkenleri ayarlamak aslında eski taahhüdün tarihini etkilemedi.
IQAndreas

36
"Bu, bunu ve gelecekteki tüm karmaları geçersiz kılacaktır" ile ne demek istiyorsun?
EpicDavi

16
EpicDavi: Bu, herhangi bir uzak depoya zorla itmeniz gerektiği anlamına gelir ve taahhüdü çeken veya gelecekte herhangi bir taahhütte bulunan herkes sıfırlamak ve çekmek veya silmek ve klondan sıfırlamak zorunda kalacaktır. Bildiğim kadarıyla bunun üstesinden gelebilecek bir yöntem yok.
EriF89

4
Sadece yeni başlayanlar için bir not olarak, kısa hash eğer açıklamada değil çalışır, uzun SHA-1 kullanmak
40detectives

780

Etkileşimli bir geri ödeme yapabilir ve tarihini değiştirmek istediğiniz taahhüt için düzenlemeyi seçebilirsiniz . Rebase işlemi, yazdığınız taahhüdü değiştirmek için durduğunda:

git commit --amend --date="Wed Feb 16 14:00 2011 +0100"

Daha sonra interaktif rebase'inize devam edersiniz.

GÜNCELLEME (studgeek yorumuna yanıt olarak): Yazar tarihi yerine taahhüt tarihini değiştirmek için:

GIT_COMMITTER_DATE="Wed Feb 16 14:00 2011 +0100" git commit --amend

Yukarıdaki satırlar, değişiklik taahhüdünde kullanılan bir ortam değişkeni GIT_COMMITTER_DATE ayarladı.

Her şey Git Bash'te test edildi.


22
@nschum --date = "" ve --data "tarih dışı metin" ifadelerinin tümü, şimdiki tarihi alarak aynıdır.
Paul Pladijs

12
Git sürüm 1.7.7.1 üzerinde --date = "now" kullanarak ölümcül: geçersiz tarih biçimi: şimdi
Aragorn

4
Tarihini değiştirmek istediğiniz taahhüt en son işlem olduğunda, bunu yapmak zorunda değilsiniz rebase, sadece yapabilirsinizgit commit --amend
Eponymous

7
GIT_COMMITTER_DATE = "" dışa aktarmak yerine GIT_COMMITTER_DATE ayarını kaldırmayı deneyin.
Mark E. Haase

2
Otomatik komut dosyalarında kullanabilmeniz için --no-edit kullanıyorum! + var fixedDate = strftime(new Date(), "%c"); + var result = shelljs.exec("git commit --amend --date=\"" + fixedDate + "\" --no-edit");
Marcello de Sales

392

Tüm bu önerileri tek bir komutta ele almanın daha iyi bir yolu

LC_ALL=C GIT_COMMITTER_DATE="$(date)" git commit --amend --no-edit --date "$(date)"

Bu, son taahhüdün taahhüt ve yazar tarihini "şu anda" olarak ayarlayacaktır.


22
Bu, etkileşimli bir rebase sırasında belirli taahhütleri düzenlemek için harika çalışır.
friederbluemle

2
Bunun için kabuğa bir takma ad da ekleyebilirsiniz
kaleissin

14
Git, tarih biçiminin yerel ayarlarından haberdar değil gibi görünüyor, bu yüzden tamamen doğru olmak için, böyle bir şey yapmanız gerekecek:LANG= GIT_COMMITTER_DATE="`date`" git commit --amend --date "`date`"
Michał Góral

Bir dalı yeniden oluşturup ezdiğimde bunu yaparım, böylece güncellenmiş bir zaman damgası ile tek bir taahhüt oluşturur.
Luke Ehresman

12
sadece yapabilirsin --date "now". Git> = 2 bunu yorumlayacaktır.
wisbucky

189

Sadece yap git commit --amend --reset-author --no-edit. Daha eski taahhütler için etkileşimli bir yeniden fiyatlandırma yapabilir ve edittarihini değiştirmek istediğiniz taahhüdü seçebilirsiniz .

git rebase -i <ref>

Sonra birlikte taahhüt değiştirebilir --reset-authorve --no-editgeçerli tarih yazar tarihi değiştirmek için:

git commit --amend --reset-author --no-edit

Son olarak etkileşimli rebase'inize devam edin:

git rebase --continue

5
iyi bir çağrı, --reset-authorgit 1.6.6'da yeni (ref gitlog.wordpress.com/2010/01/13/git-1-6-6 )
Tim Abell

1
Bu, Github'un yeniden temelli bir PR'nin taahhütlerini doğru sırada göstermesini sağlamak için iyi çalışır, çünkü onları zaman damgasıyla sipariş ederler ve bu hile olmadan, zaman damgalarının hepsi aynı olabilir.
Nathan Long

4
not --reset-author, hem Yazar'ı hem de Yazar Tarihini şimdiye kadar sıfırlayacaktır.
wisbucky

bu "KOMİTE TARİHİ" ni aynı anda değiştirecek mi?
luochen1990

134

Bunun için bir senaryo ve Homebrew paketi yazdım. Kurulumu çok kolay, GitHub PotatoLabs/git-redatesayfasında bulabilirsiniz.

Sözdizimi:

git redate -c 3

Sadece koşmanız gerekiyor git redateve tüm tarihleri ​​en son 5 komisyonun viminde düzenleyebileceksiniz ( -ckaç tane geri gitmek istediğinize dair bir seçenek de var , varsayılan olarak 5'tir). Herhangi bir sorunuz, yorumunuz veya öneriniz varsa bana bildirin!

resim açıklamasını buraya girin


2
Nano yerine vim kullanmak zorunda
olmama

@Edmund'a harika bir senaryo için teşekkürler. Git redate -c'yi çalıştırdıktan sonra vi'de düzenleme tarihini göremedim. Tüm gördüğüm% cI | XXXXXXXXXXXXXXXX | İlk taahhüt. Lütfen yardım eder misiniz? Teşekkürler
Kiem Nguyen

@KiemNguyen sadece git redate (-c olmadan) deneyebilir misiniz?
bigpotato

4
Mina ve @howdoyouturnthison ile tamamen katılıyorum, neden EDITOR ortam değişkeni üzerinden editör agnostik yapmıyorsunuz? (ayrıca ben mac üzerinde değil linux üzerindeyim ...)
ympostor

3
Teşekkürler @Edmund! Her ihtimale karşı, komut dosyanızın COMMITS için varsayılan değeri işlemeyle ilgili bir sorunu var. Ayarlanmazsa, aşağıdaki kod yalnızca son işleme (sanırım / buldum) için filtreler uygular. "git filter-branch -f --env-filter" $ ENVFILTER "HEAD ~ $ COMMITS..HEAD> / dev / null"
Grigory Entin

102

Her taahhüt, bitiş tarihi ve yazar tarihi olmak üzere iki tarihle ilişkilendirilir. Bu tarihleri ​​şununla görüntüleyebilirsiniz:

git log --format=fuller

Yazar tarihini ve son 6 taahhüdün değişme tarihini değiştirmek istiyorsanız, etkileşimli bir yeniden taban kullanabilirsiniz:

git rebase -i HEAD~6

.

pick c95a4b7 Modification 1
pick 1bc0b44 Modification 2
pick de19ad3 Modification 3
pick c110e7e Modification 4
pick 342256c Modification 5
pick 5108205 Modification 6

# Rebase eadedca..5108205 onto eadedca (6 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit

Eğer tarihi değiştirmek değiştirmek istiyor bütün kaydedilmesini için picktarafından edit(ya da sadece e), sonra kaydedin ve editörü çıkın.

Artık ISO-8601 formatında yazar tarihini ve değişiklik tarihini belirterek her bir taahhüdü değiştirebilirsiniz:

GIT_COMMITTER_DATE="2017-10-08T09:51:07" git commit --amend --date="2017-10-08T09:51:07"

İlk tarih taahhüt tarihidir, ikincisi yazar tarihidir.

Ardından bir sonraki işleme geçin:

git rebase --continue

Tüm taahhütlerinizi değiştirene kadar işlemi tekrarlayın. İlerlemenizi kontrol edin git status.


1
Bunu takip ettim ve bir 'müstakil kafa' buldum!
Simon H

1
@Simon H Cevabımı tekrar test ettim ve iyi çalışıyor. Farklı bir şey yazmış olmalısın ya da zaten müstakil bir kafadaydın. Ayrılmış bir kafadan geri dönmek istiyorsanız bir git checkout name-of-current-branch.
Ortomala Lokni

3
Bu en iyi ve en kolay cevap. Küçük bir ipucu: kullanım --no-edit içinde git commit --amend --no-edit --date=2017-10-08T09:51:07eski mesaj taahhüt tutmak.
Mariusz Pawelski

2
Ayrıca GIT_COMMITTER_DATE burada açıklandığı gibi güncellemek isteyebilirsiniz eddmann.com/posts/…
smihael

2
@smihael Bağlantı için teşekkürler. Önerinizi cevabıma ekledim.
Ortomala Lokni


44

Bina theosp 'ın cevabını aradım bir senaryo yazdım git-cdcyaşıyorum benim koymak (değişim tarih için taahhüt) PATH.

Adı önemlidir: git-xxxyazdığınız herhangi bir yer aşağıdakileri yazmanıza PATHolanak tanır:

git xxx
# here
git cdc ... 

Bu komut dosyası Windows'ta bile bash'tadır (Git msys ortamından çağıracağı için )

#!/bin/bash
# commit
# date YYYY-mm-dd HH:MM:SS

commit="$1" datecal="$2"
temp_branch="temp-rebasing-branch"
current_branch="$(git rev-parse --abbrev-ref HEAD)"

date_timestamp=$(date -d "$datecal" +%s)
date_r=$(date -R -d "$datecal")

if [[ -z "$commit" ]]; then
    exit 0
fi

git checkout -b "$temp_branch" "$commit"
GIT_COMMITTER_DATE="$date_timestamp" GIT_AUTHOR_DATE="$date_timestamp" git commit --amend --no-edit --date "$date_r"
git checkout "$current_branch"
git rebase  --autostash --committer-date-is-author-date "$commit" --onto "$temp_branch"
git branch -d "$temp_branch"

Bununla şunu yazabilirsiniz:

git cdc @~ "2014-07-04 20:32:45"

Bu, HEAD ( @~) öncesindeki taahhüdün yazar / teslim tarihini belirtilen tarihe sıfırlar .

git cdc @~ "2 days ago"

Bu, HEAD ( @~) öncesi taahhüdün yazar / taahhüt tarihini aynı saate, ancak 2 gün önce sıfırlar .


İlya Semenov bahseder yorumlarda :

OS X için ayrıca GNU coreutils( brew install coreutils) yükleyebilir , PATH( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") öğesine ekleyebilir ve sonra " 2 days ago" sözdizimini kullanabilirsiniz .


1
Benim için bu sadece tarih ve saati tek bir alıntıda alıntılamakla çalıştı: git cdc @~ "2014-07-04 20:32:45aksi takdirde saati tanımayacak ve dolayısıyla 00:00:00 (üçüncü argüman haline gelir).
peschü

3
OS X için ayrıca GNU coreutils ( brew install coreutils) yükleyebilir , PATH ( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH") öğesine ekleyebilir ve sonra "2 gün önce" sözdizimini kullanabilirsiniz.
Ilya Semenov

1
@IlyaSemenov İlginç. Daha fazla görünürlük için yorumunuzu cevaba ekledim.
VonC

İlk örneğinizi kullanmaya çalışıyorum ama "ölümcül: geçersiz tarih biçimi:" almaya devam ediyorum. Mac OS X hangi tarih biçimini bekliyor?
usbsnowcrash

@usbsnowcrash Mac'te emin değilim. İkinci örnek " 2 days ago" işe yarıyor mu?
VonC

25

Birden Çok Teslim Tarihini Düzenleme

Diğer yanıtlar, birkaç kesinleştirme tarihini düzenlemek için çok uygun değildir. Birkaç yıl sonra bir tekniği paylaşmak için bu soruya geri döndüm.

Son 4 işlemin tarihini değiştirmek için:

git rebase -i HEAD~4

execTarihleri ​​gerektiği gibi değiştirmek için satır ekleyerek yeniden tabanı aşağıdaki gibi düzenleyin:

pick 4ca564e Do something
exec git commit --amend --no-edit --date "1 Oct 2019 12:00:00 PDT"
pick 1670583 Add another thing
exec git commit --amend --no-edit --date "2 Oct 2019 12:00:00 PDT"
pick b54021c Add some tests
exec git commit --amend --no-edit --date "3 Oct 2019 12:00:00 PDT"
pick e8f6653 Fix the broken thing
exec git commit --amend --no-edit --date "4 Oct 2019 12:00:00 PDT"

--amend/ --dateSeçeneğini güzel kullanımı . Ortam değişkenlerini kullanarak kendi cevabımdan daha basit . Upvoted.
VonC

Geçerli tarih / saati parametre olarak kullanmak mümkün müdür?
accfews

Bu GIT_AUTHOR_DATEsadece güncellenir .
Blaise

Yeniden. 'Geçerli tarih / saati parametre olarak kullanmak mümkün mü?': "Now" geçerli bir tarih olarak anlaşılıyor, bu nedenle yukarıdaki yürütme satırları şu olacakexec git commit --amend --no-edit --date "now"
Andrew Richards

20

önceki son taahhüt ise.

git rebase  -i HEAD~2
git commit --amend --date=now

zaten orgin'e zorlarsanız ve kullanımı zorlayabilirseniz:

git push --force 

eğer itmeyi zorlayamazsanız ve itilirse, taahhüdü değiştiremezsiniz! .


18

Aşağıda, son taahhüdün hem kesin hem de yazar zamanlarını kabul eden bir zamana değiştiren kullanışlı bir takma ad verilmiştir date --date:

[alias]
    cd = "!d=\"$(date -d \"$1\")\" && shift && GIT_COMMITTER_DATE=\"$d\" \
            git commit --amend --date \"$d\""

Kullanımı: git cd <date_arg>

Örnekler:

git cd now  # update the last commit time to current time
git cd '1 hour ago'  # set time to 1 hour ago

Düzenleme: İşte dizinin temiz (taahhüt edilmemiş değişiklik yok) ve son taahhüt iletisini yeniden kullanır veya aksi takdirde (kusursuz) başarısız olup olmadığını kontrol eden daha otomatik bir sürüm:

[alias]
    cd = "!d=\"$(date -d \"$1\")\" && shift && \
        git diff-index --cached --quiet HEAD --ignore-submodules -- && \
        GIT_COMMITTER_DATE=\"$d\" git commit --amend -C HEAD --date \"$d\"" \
        || echo >&2 "error: date change failed: index not clean!"

17

Eski taahhütlerin tarihini değiştirmek için bu npm paketini oluşturdum.

https://github.com/bitriddler/git-change-date

Örnek Kullanımı:

npm install -g git-change-date
cd [your-directory]
git-change-date

Değiştirmek istediğiniz taahhüdü seçmeniz ve ardından yeni tarihi girmeniz istenir.

Belirli bir hash ile bir taahhüdü değiştirmek istiyorsanız bunu çalıştırın git-change-date --hash=[hash]


Sadece bunun harika olduğunu ve güzel çalıştığını söylemek istedim. Teşekkür ederim, bana çok zaman kazandın!
paranza

17

Aşağıdaki bash işlevi, geçerli daldaki herhangi bir taahhüdün süresini değiştirecektir.

Taahhüt işlemini daha önce ittiyseniz veya başka bir dalda kullandıysanız kullanmamaya dikkat edin.

# rewrite_commit_date(commit, date_timestamp)
#
# !! Commit has to be on the current branch, and only on the current branch !!
# 
# Usage example:
#
# 1. Set commit 0c935403 date to now:
#
#   rewrite_commit_date 0c935403
#
# 2. Set commit 0c935403 date to 1402221655:
#
#   rewrite_commit_date 0c935403 1402221655
#
rewrite_commit_date () {
    local commit="$1" date_timestamp="$2"
    local date temp_branch="temp-rebasing-branch"
    local current_branch="$(git rev-parse --abbrev-ref HEAD)"

    if [[ -z "$date_timestamp" ]]; then
        date="$(date -R)"
    else
        date="$(date -R --date "@$date_timestamp")"
    fi

    git checkout -b "$temp_branch" "$commit"
    GIT_COMMITTER_DATE="$date" git commit --amend --date "$date"
    git checkout "$current_branch"
    git rebase "$commit" --onto "$temp_branch"
    git branch -d "$temp_branch"
}

1
Orada bir hata var: if [[ -z "$commit" ]]->if [[ -z "$date_timestamp" ]]
blueFast

Güzel! GIT_COMMITTER_DATE=Herhangi bir manuel taahhüdün belirtilen tarihi muhafaza etmesini önlemek için yöntemin sonunda ayar yapılmasını tavsiye ederim .
loopkin

@loopkin, GIT_COMMITTER_DATE sadece "git commit" komutu için ayarlanmış, bu yüzden daha sonra temizlemeye gerek yok
nimrodm

@ nimrodm, tekrar test ettim ve haklısın. Bunu işaret ettiğiniz için teşekkürler.
loopkin

12

Hem yazar tarihini hem de bitiş tarihini değiştirmek için:

GIT_COMMITTER_DATE="Wed Sep 23 9:40 2015 +0200" git commit --amend --date "Wed Sep 23 9:40 2015 +0200"

10

Başka bir taahhüdün tam tarihini almak istiyorsanız (bir taahhüdü yeniden düzenlediğinizi ve orijinal ön-ön sürüm sürümünün tarihine sahip olmasını istediğinizi varsa):

git commit --amend --date="$(git show -s --format=%ai a383243)"

Bu, HEAD taahhüt tarihini tam olarak a383243 taahhüt tarihi olarak düzeltir (belirsizlikler varsa daha fazla basamak ekleyin). Ayrıca, taahhüt mesajını düzenleyebilmeniz için bir düzenleyici penceresi açılır.

Bu, genellikle önem verdiğiniz yazar tarihi içindir - başlama tarihi için diğer cevaplara bakın.


7

Kabul edilen yanıtı ( https://stackoverflow.com/a/454750/72809 ) standart Windows komut satırında gerçekleştirmek istiyorsanız, aşağıdaki komuta ihtiyacınız vardır:

git filter-branch -f --env-filter "if [ $GIT_COMMIT = 578e6a450ff5318981367fe1f6f2390ce60ee045 ]; then export GIT_AUTHOR_DATE='2009-10-16T16:00+03:00'; export GIT_COMMITTER_DATE=$GIT_AUTHOR_DATE; fi"

Notlar:

  • Komutu birden çok satıra bölmek mümkün olabilir (Windows carret sembolü ile satır bölmeyi destekler ^), ancak başarılı olamadım.
  • ISO tarihlerini yazabilir, öğelerin sırasına göre doğru haftanın gününü ve genel hayal kırıklığını bulmak için çok zaman kazanabilirsiniz.
  • Yazar ve Committer tarihinin aynı olmasını istiyorsanız, önceden ayarlanan değişkene başvurabilirsiniz.

Çok teşekkürler Colin Svingen'in blog gönderisine gidiyor . Kodu benim için işe yaramasa da, doğru çözümü bulmama yardımcı oldu.


7

Taahhüt henüz itilmemişse, böyle bir şey kullanabilirim:

git commit --amend --date=" Wed Mar 25 10:05:44 2020 +0300"

ondan sonra git bash editörü zaten uygulanmış olan tarihle açar, bu nedenle VI editörü ": wq" komut kipinde yazarak kaydetmeniz yeterlidir.


2
Sadece güzel cevaba ekleyerek: taahhüt mesajını düzenlemek istemiyorsanız (sadece taahhüt tarihini değiştirmek istiyorsanız), --no-editseçeneği kullanın.
Antonio Vinicius Menezes Medei

Ayrıca, taahhüt zaten itilmişse, git push -f(zorunlu güncelleme) düğmesini kullanarak değiştirilmiş taahhüdü yine de itebilirsiniz . Yine de bunun yan etkileri olabilir. (özellikle birçok insanın deponun yerel klonları varsa)
Antonio Vinicius Menezes Medei


2

Zaten çok sayıda harika cevap var, ancak bir gün veya bir ay içinde birden fazla taahhüt için tarihi değiştirmek istediğimde, doğru bir cevap bulamıyorum. Bu yüzden açıklama ile bunun için yeni bir senaryo oluşturuyorum, umarım birisine yardımcı olur:

#!/bin/bash

# change GIT_AUTHOR_DATE for commit at Thu Sep 14 13:39:41 2017 +0800
# you can change the data_match to change all commits at any date, one day or one month
# you can also do the same for GIT_COMMITTER_DATE

git filter-branch --force --env-filter '

date_match="^Thu, 14 Sep 2017 13+"              

# GIT_AUTHOR_DATE will be @1505367581 +0800, Git internal format 
author_data=$GIT_AUTHOR_DATE;                   
author_data=${author_data#@}                  
author_data=${author_data% +0800}                # author_data is 1505367581     

oneday=$((24*60*60))

# author_data_str will be "Thu, 14 Sep 2017 13:39:41 +0800", RFC2822 format
author_data_str=`date -R -d @$author_data`      

if [[ $author_data_str =~ $date_match ]];
then
    # remove one day from author_data
    new_data_sec=$(($author_data-$oneday))
    # change to git internal format based on new_data_sec
    new_data="@$new_data_sec +0800"             
    export GIT_AUTHOR_DATE="$new_data"
fi
' --tag-name-filter cat -- --branches --tags

Tarih değiştirilecek:

AuthorDate: Wed Sep 13 13:39:41 2017 +0800
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.