Git에서 오래된 커밋의 타임 스탬프를 어떻게 바꿀 수 있습니까?


746

푸시되지 않은 기존 커밋을 수정하는 방법에 대한 답변 은 무엇입니까? 아직 업스트림으로 푸시되지 않은 이전 커밋 메시지를 수정하는 방법을 설명합니다. 새 메시지는 원래 커밋의 타임 스탬프를 상속합니다. 이것은 논리적으로 보이지만 시간을 다시 설정하는 방법이 있습니까?



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

답변:


535

수정하려는 커밋의 특정 해시 git filter-branch를 설정 GIT_AUTHOR_DATE하고 env 필터와 함께 사용하십시오 GIT_COMMITTER_DATE.

이것은 그와 모든 미래의 해시를 무효화합니다.

예:

commit 날짜 를 변경하려면 119f9ecf58069b265ab22f1f97d2b648faf932e0다음과 같이하면됩니다.

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
발견 올바른 값을, 그러나 다만 그 변수는 실제로 커밋 이전의 날짜에 영향을 미칠 것 같지 않았다 설정.
IQAndreas

36
"이것은 모든 해시를 무효화합니다."는 무엇을 의미합니까?
EpicDavi

16
EpicDavi : 원격 저장소에 강제로 푸시해야하고 커밋 또는 향후 커밋을 가져온 사람은 처음부터 재설정, 풀 또는 삭제 및 복제해야합니다. 내가 아는 한이 문제를 해결할 방법이 없습니다.
EriF89

4
초보자를위한 참고 사항으로, 짧은 해시는 if 문에서 작동하지 않습니다. 긴 SHA-1
40detectives를 사용하십시오.

780

대화식 리베이스를 수행하고 날짜를 변경하려는 커밋에 대한 편집 을 선택할 있습니다. 리베이스 프로세스가 커밋을 수정하기 위해 중지되면 다음과 같이 입력하십시오.

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

이후에 대화식 리베이스를 계속합니다.

업데이트 (studgeek의 의견에 대한 응답으로) : 작성자 날짜 대신 커밋 날짜를 변경하려면 다음을 수행하십시오.

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

위의 줄은 수정 커밋에 사용되는 환경 변수 GIT_COMMITTER_DATE를 설정합니다.

모든 것이 Git Bash에서 테스트됩니다.


22
@nschum --date = ""및 --data "non-date-text"는 모두 현재 날짜를 사용하여 동일하게 산출됩니다.
Paul Pladijs

12
git 버전 1.7.7.1에서 --date = "now"를 사용하면 치명적 : 잘못된 날짜 형식이 표시됩니다. now
Aragorn

4
날짜를 변경하려는 커밋이 가장 최근의 커밋 인 rebasegit commit --amend
경우을

7
GIT_COMMITTER_DATE = ""내보내기 대신 GIT_COMMITTER_DATE 설정을 해제하십시오.
Mark E. Haase

2
자동화 된 스크립트에서 사용할 수 있도록 --no-edit를 사용하고 있습니다! + var fixedDate = strftime(new Date(), "%c"); + var result = shelljs.exec("git commit --amend --date=\"" + fixedDate + "\" --no-edit");
Marcello de Sales 0시 19 분

392

하나의 명령으로 이러한 제안을 모두 처리하는 더 좋은 방법은

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

그러면 마지막 커밋의 커밋 및 작성자 날짜가 "지금"으로 설정됩니다.


22
이것은 대화식 리베이스 동안 특정 커밋을 편집하는 데 효과적입니다.
friederbluemle

2
당신은 그것도 쉘에 별칭을 추가 할 수 있습니다
kaleissin

14
Git이 날짜 형식을 로케일을 인식하지 못하는 것 같으므로 완전히 정확하려면 다음과 같이 만들어야합니다.LANG= GIT_COMMITTER_DATE="`date`" git commit --amend --date "`date`"
Michał Góral

분기를 리베이스하고 스쿼시 할 때 업데이트되므로 타임 스탬프가 업데이트 된 단일 커밋이 생성됩니다.
Luke Ehresman

12
당신은 또한 할 수 있습니다 --date "now". 힘내> = 2는 그것을 해석 할 것입니다.
wisbucky

189

그냥하세요 git commit --amend --reset-author --no-edit. 이전 커밋의 경우 대화식 리베이스를 수행하고 edit날짜를 수정하려는 커밋을 선택할 수 있습니다.

git rebase -i <ref>

그런 다음이 함께 커밋 수정 --reset-author하고 --no-edit현재 날짜로 저자 날짜를 변경하는 :

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

마지막으로 대화식 리베이스를 계속하십시오.

git rebase --continue

5
사용에 대한 좋은 호출 --reset-author, 그것은 자식의 새로운 1.6.6 (REF gitlog.wordpress.com/2010/01/13/git-1-6-6 )
팀 아벨

1
이것은 타임 스탬프별로 순서를 정하고이 트릭없이 타임 스탬프가 모두 같을 수 있기 때문에 Github이 재순환 된 PR의 커밋을 올바른 순서로 표시하도록하는 데 효과적 입니다.
Nathan Long

4
note --reset-author는 작성자와 작성자 날짜를 모두 지금 재설정합니다.
wisbucky

"COMMITTER DATE"가 동시에 변경됩니까?
luochen1990

134

이를 위해 스크립트와 Homebrew 패키지를 작성했습니다. 설치가 매우 쉽고 GitHub PotatoLabs/git-redate페이지 에서 찾을 수 있습니다 .

통사론:

git redate -c 3

당신은 실행해야 git redate하고 가장 최근의 5 커밋의 vim에서 모든 날짜를 편집 할 수 있습니다 ( -c다시 커밋하려는 커밋 수에 대한 옵션 도 있으며 기본값은 5입니다). 질문, 의견 또는 제안 사항이 있으면 알려주십시오!

여기에 이미지 설명을 입력하십시오


2
비록 나노보다는 vim을 사용해야했지만 훌륭한 것들
howdoyouturnthison

훌륭한 스크립트에 감사드립니다. git redate -c를 실행 한 후 vi에서 편집 날짜를 볼 수 없습니다. 내가 보는 것은 % cI | XXXXXXXXXXXXXXXX | 초기 커밋. 도와 주시겠습니까? 감사합니다
Kiem Nguyen

@KiemNguyen 그냥 -c없이 git redate를 시도해 볼 수 있습니까?
bigpotato

4
여기 Mina와 @howdoyouturnthison에 완전히 동의합니다. EDITOR 환경 변수를 통해 에디터를 불가지론 적으로 만드시겠습니까? (또한 Mac이 아닌 Linux에 있습니다 ...)
ympostor

3
감사합니다 @ Edmund! COMMITS의 기본값을 처리하는 데 스크립트에 문제가있는 경우를 대비하여. 설정되어 있지 않으면 다음 코드는 마지막 커밋에만 필터를 적용합니다. "git filter-branch -f --env-filter"$ ENVFILTER "HEAD ~ $ COMMITS..HEAD> / dev / null"
Grigory Entin

101

각 커밋은 커미터 날짜와 작성자 날짜의 두 날짜와 연결됩니다. 이 날짜를 다음과 같이 볼 수 있습니다.

git log --format=fuller

마지막 6 개의 커밋의 작성자 날짜와 커미터 날짜를 변경하려면 대화식 rebase를 사용하면됩니다.

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

당신이 날짜를 변경 대체 할 모든 커밋 pick에 의해 edit(또는 e), 다음 저장하고 편집기를 종료합니다.

이제 작성자 날짜와 커미터 날짜를 ISO-8601 형식으로 지정하여 각 커밋을 수정할 수 있습니다.

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

첫 번째 날짜는 커밋 날짜이고 두 번째 날짜는 제작 날짜입니다.

그런 다음 다음 커밋으로 이동하십시오.

git rebase --continue

커밋을 모두 수정할 때까지 프로세스를 반복하십시오. 로 진행 상황을 확인하십시오 git status.


1
나는 이것을 따라 '분리 된 머리'로 끝났다!
Simon H

1
@Simon H 나는 다시 대답을 테스트했으며 잘 작동합니다. 다른 것을 입력했거나 이미 분리 된 헤드에있었습니다. 분리 된 헤드에서 돌아 오려면를 수행하십시오 git checkout name-of-current-branch.
Ortomala Lokni

3
이것이 가장 좋고 가장 쉬운 대답입니다. 작은 팁 : --no-edit in git commit --amend --no-edit --date=2017-10-08T09:51:07을 사용 하여 기존 커밋 메시지를 유지하십시오.
Mariusz Pawelski

2
GIT_COMMITTER_DATE 여기에 설명 된대로 업데이트 할 수도 있습니다. eddmann.com/posts/…
smihael

2
@smihael 링크 감사합니다. 답변에 귀하의 제안을 포함 시켰습니다.
Ortomala Lokni


44

theosp답변바탕으로 , 나는 git-cdc(변경 날짜 커밋을 위해) 라는 스크립트를 작성했습니다 PATH.

이름은 중요합니다. git-xxx어디에서나 PATH입력 할 수 있습니다.

git xxx
# here
git cdc ... 

그 스크립트는 Windows에서도 bash에 있습니다 (Git이 msys 환경 에서 스크립트를 호출하기 때문에 )

#!/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"

이를 통해 다음을 입력 할 수 있습니다.

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

HEAD 이전 커밋의 작성자 / 커밋 날짜 ( @~)를 지정된 날짜로 재설정 합니다.

git cdc @~ "2 days ago"

그러면 HEAD ( @~) 이전 커밋의 작성자 / 커밋 날짜가 같은 시간으로 재설정 되지만 2 일 전에 다시 설정됩니다.


Ilya Semenov주석에서 언급 했습니다 .

OS X의 경우 당신은 또한 GNU 설치할 수 있습니다 coreutils( brew install coreutils에 추가)를 PATH( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH""사용 후) 및 2 days ago"구문을.


1
나를 위해 이것은 날짜와 시간을 작은 따옴표로 인용하는 것만으로 작동했습니다. git cdc @~ "2014-07-04 20:32:45그렇지 않으면 시간을 인식하지 못하므로 시간 00:00:00을 얻습니다 (세번째 인수가됩니다).
peschü

3
OS X의 경우 GNU coreutils ( brew install coreutils)를 설치 하고 PATH ( PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH")에 추가 한 다음 "2 일 전"구문을 사용할 수도 있습니다.
Ilya Semenov

1
@IlyaSemenov 재미있는. 더 많은 가시성을 제공하기 위해 귀하의 의견을 답변에 포함 시켰습니다.
VonC

첫 번째 예를 사용하려고하는데 "치명적 : 유효하지 않은 날짜 형식 :"이 계속 표시됩니다. Mac OS X는 어떤 날짜 형식을 기대합니까?
usbsnowcrash 2016 년

@usbsnowcrash는 Mac에서 확실하지 않습니다. 두 번째 예 " 2 days ago"가 작동합니까?
VonC 2016 년

25

여러 커밋 날짜를 편집하는 방법

다른 답변은 여러 커밋 날짜를 편집하는 데별로 편리하지 않습니다. 몇 년 후에 기술을 공유하기 위해이 질문으로 돌아 왔습니다.

마지막 4 개의 커밋 날짜를 변경하려면

git rebase -i HEAD~4

exec필요에 따라 날짜를 수정하기 위해 줄을 삽입하여 다음과 같이 리베이스를 편집하십시오 .

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/의 --date옵션을 선택합니다. 환경 변수를 사용하는 내 대답 보다 간단 합니다. 공감.
VonC

현재 날짜 / 시간을 매개 변수로 사용할 수 있습니까?
18

업데이트 GIT_AUTHOR_DATE만합니다.
블 레즈

레. '현재 날짜 / 시간을 매개 변수로 사용할 수 있습니까?': "지금"은 유효한 날짜로 이해되므로 위의 exec 행은 다음과 같이됩니다.exec git commit --amend --no-edit --date "now"
Andrew Richards

20

이전의 마지막 커밋 인 경우

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

이미 시작을 강요하고 강제로 사용할 수있는 경우 :

git push --force 

푸시를 강제 할 수없고 푸시되면 커밋을 변경할 수 없습니다! .


18

다음은 마지막 커밋의 커밋 및 작성 시간을 모두 허용되는 시간으로 변경하는 편리한 별칭입니다 date --date.

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

용법: git cd <date_arg>

예 :

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

편집 : 다음은 인덱스가 깨끗한 지 (커밋되지 않은 변경 사항 없음) 확인하고 마지막 커밋 메시지를 다시 사용하거나 그렇지 않으면 실패하지 않는 자동화 된 버전입니다.

[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

이전 커밋 날짜를 변경하기 위해이 npm 패키지를 만들었습니다.

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

샘플 사용법 :

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

수정하려는 커밋을 선택한 다음 새 날짜를 입력하라는 메시지가 표시됩니다.

특정 해시로 커밋을 변경하려면 이것을 실행하십시오. git-change-date --hash=[hash]


나는 이것이 훌륭하고 아름답게 작동한다고 말하고 싶었습니다. 감사합니다. 시간을 많이 절약하셨습니다!
paranza

17

다음 bash 함수는 현재 브랜치에서 커밋 시간을 변경합니다.

커밋을 이미 푸시했거나 다른 분기에서 커밋을 사용하는 경우 사용하지 않도록주의하십시오.

# 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
당신은 거기에 버그가 있습니다 : if [[ -z "$commit" ]]->if [[ -z "$date_timestamp" ]]
blueFast

좋은! GIT_COMMITTER_DATE=메소드가 끝날 때 수동 커밋을 지정하여 날짜를 지정하지 않도록 설정 하는 것이 좋습니다 .
loopkin

@loopkin, GIT_COMMITTER_DATE는 "git commit"명령에 대해서만 설정되므로 나중에 지우지 않아도됩니다.
nimrodm

@nimrodm, 나는 방금 다시 테스트했고 당신은 정확합니다. 지적 해 주셔서 감사합니다.
loopkin

12

작성 날짜와 커밋 날짜를 모두 변경하려면

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

10

다른 커밋의 정확한 날짜를 얻으려면 (예를 들어 커밋을 리베이스 편집하고 원래 프리 리베이스 버전의 날짜를 갖기를 원할 경우) :

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

이렇게하면 HEAD 커밋 날짜가 커밋 날짜 가 정확히 a383243 이되도록 수정합니다 (모호한 경우 더 많은 숫자 포함). 커밋 메시지를 편집 할 수있는 편집기 창이 나타납니다.

그것은 당신이 일반적으로 관심있는 저작자 날짜입니다-커미터 날짜에 대한 다른 답변을보십시오.


7

표준 Windows 명령 행에서 허용되는 응답 ( https://stackoverflow.com/a/454750/72809 ) 을 수행 하려면 다음 명령이 필요합니다.

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"

노트:

  • 명령을 여러 줄로 나누는 것이 가능할 수 있습니다 (Windows는 캐럿 기호가있는 줄 나누기를 지원합니다) ^ ) 성공하지 못했습니다.
  • ISO 날짜를 작성할 수 있으므로 요소 순서에 따라 올바른 요일 및 일반적인 좌절감을 찾는 데 많은 시간을 절약 할 수 있습니다.
  • 작성자와 커미터 날짜를 동일하게하려면 이전에 설정 한 변수를 참조하면됩니다.

Colin Svingen블로그 게시물에 많은 감사를드립니다 . 그의 코드가 나를 위해 작동하지 않았지만 올바른 솔루션을 찾는 데 도움이되었습니다.


7

커밋이 아직 푸시되지 않은 경우 다음과 같은 것을 사용할 수 있습니다.

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

그 후 git bash는 이미 적용된 날짜로 편집기를 열므로 VI 편집기 명령 모드 ": wq"를 입력하여 저장하면됩니다.


2
좋은 대답에 추가하기 만하면 : 커밋 메시지를 편집하지 않으려면 (커밋 날짜를 변경하려는 경우) --no-edit옵션을 사용하십시오 .
Antonio Vinicius Menezes Medei

또한 커밋이 이미 푸시 된 경우에도 git push -f(강제 업데이트)를 사용하여 변경된 커밋을 푸시 할 수 있습니다 . 그러나 부작용이있을 수 있습니다. (특히 많은 사람들이 저장소의 로컬 클론을 가지고있는 경우)
Antonio Vinicius Menezes Medei


2

이미 많은 훌륭한 답변이 있지만 하루 또는 한 달 안에 여러 커밋에 대한 날짜를 변경하고 싶을 때 적절한 답변을 찾지 못했습니다. 그래서 나는 설명과 함께 이것을 위해 새로운 스크립트를 만듭니다. 그것이 누군가를 도울 수 있기를 바랍니다.

#!/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

날짜가 변경됩니다 :

AuthorDate: Wed Sep 13 13:39:41 2017 +0800
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.