커밋 타임 스탬프를 변경하지 않고 git rebase


157

git rebase커밋 타임 스탬프를 유지하면서 수행 하는 것이 합리적 입니까?

나는 새로운 지점이 반드시 연대순으로 날짜를 가질 필요는 없다고 생각합니다. 즉 이론적으로 전혀 가능? (예 : 배관 명령 사용; 여기서 궁금한 점)

이론적으로 가능하다면 실제로 타임 스탬프를 변경하지 않고 rebase를 사용하는 것이 가능합니까?

예를 들어 다음과 같은 트리가 있다고 가정합니다.

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

나는 리베이스 지금, 만약 oldbranchmaster,의 날짜는 가능 시간 소인이 변경되지 않습니다 커밋되도록 동작을 변경 6월 2010 년에 2 월 1984 년부터 변경 사항을 커밋? 결국 나는 이렇게 얻을 것이다 :

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

그게 말이 되겠습니까? git에서 오래된 커밋이 더 최근의 커밋을 가진 기록을 가질 수 있습니까?


3
이 질문에 대한 답은 실제로 "아무것도 할 필요가 없습니다-그것이 기본적으로 작동하는 방식입니다"라는 것이 펑키합니다. 그러나 이제 rebase를 수행하면서 commit을 올바른 날짜 순서로 정렬한다고 가정하십시오 (생각하면 꽤 자연스러운 시나리오입니다). 지금, 나는 그것을 달성하는 방법을 찾을 수 없었고 내 q를 stackoverflow.com/questions/12270357/really-flatten-a-git-merge
pfalcon

1
David는 커미터 날짜를 재설정하는 또 다른 옵션을 언급합니다 git rebase --committer-date-is-author-date SHA. 아래에서 편집 한 답변
VonC 2016 년

필자 는 저자가 여기에 설명 된 답변을 시도했지만 만족스럽게 적용 할 수없는 비슷한 질문 에 대한 광범위한 답변 을 썼습니다 .
axiac

답변:


149

2014 년 6 월 업데이트 : David Fraser코멘트 에서 옵션을 사용하여 " git 브랜치를 리베이스하는 동안 타임 스탬프 변경 "에 설명 된 솔루션을 언급 했습니다--committer-date-is-author-date (2009 년 1 월 커밋 3f01ad6 에서 도입 됨).

--committer-date-is-author-date옵션은 작성자 타임 스탬프를 남기고 커미터 타임 스탬프를 OP Olivier Verdier가 원했던 원래 작성자 타임 스탬프와 동일하게 설정합니다 .

올바른 날짜의 마지막 커밋을 발견하고 다음을 수행했습니다.

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

참조 git am:

--committer-date-is-author-date

기본적으로 명령은 전자 우편 메시지의 날짜를 커미트 작성자 날짜로 기록하고 커미트 작성 시간을 커미터 날짜로 사용합니다.
이를 통해 사용자는 작성자 날짜와 동일한 값을 사용하여 커미터 날짜에 대해 거짓말을 할 수 있습니다 .


(원래 답변, 2012 년 6 월)

비 대화식 rebase 를 시도해 볼 수 있습니다.

git rebase --ignore-date

(이 SO 답변에서 )

이에 전달됩니다 git am.

 --ignore-date

기본적으로 명령은 전자 우편 메시지의 날짜를 커미트 작성자 날짜로 기록하고 커미트 작성 시간을 커미터 날짜로 사용합니다.
이를 통해 사용자는 커미터 날짜와 동일한 값을 사용하여 작성자 날짜에 대해 거짓말을 할 수 있습니다.

git rebase경우이 옵션은 "--interactive 옵션과 호환되지 않습니다."

때문에 당신이 기존의 타임 스탬프 날짜를 저지 마음대로 변경할 수 있습니다 (과 git filter-branch), 당신도, 당신이 원하는 날짜 순서 / 필요성을 커밋 무엇 이건 당신의 망할 놈의 기록을 구성 할 수 있습니다 가정 미래로 설정! .


Olivier 가 그의 질문에서 언급 했듯이 , 저작 날짜 는 리베이스에 의해 변경되지 않습니다.
로부터 프로 힘내 도서 :

  • 저자는 원래 작품을 쓴 사람입니다.
  • 커미터는 작업을 마지막으로 적용한 사람입니다.

따라서 프로젝트에 패치를 보내고 핵심 멤버 중 하나가 패치를 적용하면 둘 다 크레딧을 얻게됩니다.

이 경우 Olivier가 다음과 같이 명확하게 설명합니다.

--ignore-date내가 달성하려고했던 것과 반대를하지 않습니다 !
즉, 작성자의 타임 스탬프를 지우고 커밋 타임 스탬프로 바꿉니다!
내 질문에 대한 정답은 다음과 같습니다. 실제로는 작성자의 타임 스탬프를 기본적으로 변경하지 않기
때문에 아무 것도하지 마십시오 git rebase.



1
커밋 할 임의의 날짜에 관심이 있습니다. 그러나 git rebase --ignore-date작동하지 않습니다. 리베이스 된 커밋 날짜를 변경합니다.
Olivier Verdier 2018 년

@Olivier : 이상하다 : 당신은 비대화 형 리베이스 를 만들 었는가? 그리고 작성자 날짜와 커미터 날짜 사이에 "올바른"날짜를 모니터링해야합니까?
VonC

1
작성자와 커미터 타임 스탬프의 차이점 인 VonC에 감사의 말을 전합니다. 나는 내 게시물에 내 질문에 대한 답변을 썼지 만 그것을 반영하도록 자유롭게 대답하십시오.
Olivier Verdier

4
(가) : 더 정확합니다 --ignore-date않습니다 반대 내가 달성하기 위해 노력했다 무엇을! 즉, 작성자의 타임 스탬프를 지우고 커밋 타임 스탬프로 바꿉니다! 내 질문에 대한 정답은 : git rebase기본적으로 작성자의 타임 스탬프를 변경하지 않기 때문에 아무것도하지 마십시오 .
Olivier Verdier 2018 년

5
--committer-date-is-author-date옵션은 작성자 타임 스탬프를 남기고 커미터 타임 스탬프를 Olivier가 원했던 원래 작성자 타임 스탬프와 동일하게 설정 한 것 같습니다.
David Fraser

118

커밋 날짜를 이미 정하고 (아마도 리베이스가있는 경우) 해당 작성자 날짜로 재설정하려는 경우 다음을 실행할 수 있습니다.

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


1
방금 시도했지만 효과가 없습니다. 나는 다음과 같은 결과를 얻었습니다 WARNING: Ref 'refs/heads/master' is unchanged. 나는 리눅스에 자식 버전 1.7.9.5을 사용하고 있습니다 (64 비트)
마커스 N.

20
이미 망쳐 놓았지만 전체 히스토리를 반복하지 않으려는 경우 다른 방법을 추가하고 싶습니다. git rebase --committer-date-is-author-date <base_branch> 이 방법으로 git은 <base_branch>에 적용된 커밋에 대해서만 커밋 날짜를 재설정합니다. 망 쳤을 때 사용한 같은 브랜치 이름).
speakman

2016 년에 수락 된 답변이 작동하지 않았지만 @speakman의 답변이 작동했습니다!
Theodore R. Smith

2
@speakman의 답변은 2016 년 10 월에 작동하지 않았지만 Andy 's는 작동했습니다!
Amedee Van Gasse

2
Windows에서는 작동하지 않습니다. Windows Bash를 사용하여 작동시킬 수있었습니다.
vaindil

33

Von C에 대한 중요한 질문은 진행 상황을 이해하는 데 도움이되었습니다. 리베이스, 커미터의 타임 스탬프는 변경되지만 저자의 타임 스탬프는 변경되지 않습니다 . 그래서 내 질문은 실제로 충분히 정확하지 않았습니다.

대답은 rebase가 실제로 저자의 타임 스탬프를 변경하지 않는다는 것입니다 (아무것도 할 필요가 없습니다).


3
+ 1- 커미터의 타임 스탬프를 분명히 사용 하는 git 별칭이 있습니다 ( coderwall.com/p/euwpig/a-better-git-log ). Gitk와 git log는 저자의 타임 스탬프를 보여줍니다.
1615903

15

기본적으로 git rebase는 커미터의 타임 스탬프를 새 커밋이 생성 된 시간으로 설정하지만 작성자의 타임 스탬프는 그대로 유지합니다. 대부분의 경우 이것은 바람직한 동작이지만 일부 시나리오에서는 커미터의 타임 스탬프도 변경하고 싶지 않습니다. 우리는 어떻게 그것을 달성 할 수 있습니까? 글쎄, 여기 내가 일반적으로하는 트릭이 있습니다.

먼저 리베이스하려는 커밋마다 고유 한 커밋 메시지와 작성자 타임 스탬프가 있는지 확인하십시오 (여기서는 트릭 개선이 필요한 곳이며 현재는 내 요구에 맞습니다).

리베이스하기 전에, 커미터의 타임 스탬프, 작성자의 타임 스탬프 및 파일로 리베이스 될 모든 커밋의 커밋 메시지를 기록하십시오.

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

그런 다음 실제 리베이스를 수행하십시오.

마지막으로 커밋 메시지가 동일한 경우 현재 커미터의 타임 스탬프를 파일에 기록 된 타임 스탬프로 바꿉니다 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'

문제가 발생하면 체크 아웃 git reflog또는 모든 refs/original/심판을 확인하십시오.

Furthormore, 저자의 타임 스탬프와 비슷한 작업을 수행 할 수 있습니다.

예를 들어, 일부 커밋에 대한 작성자의 타임 스탬프가 순서가 맞지 않고 이러한 커밋을 재 배열하지 않으면 저자의 타임 스탬프가 순서대로 표시되기를 원하면 다음 명령이 도움이됩니다.

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'

이것은 훌륭한 트릭입니다! 다른 답변을 사용하지 않고 1100 + 대신 75 커밋을 다시 작성할 수있었습니다.
audun

환상적이다! 원본 커미터도 유지하도록 스크립트를 수정하는 방법이 있습니까?
David DeMar

@DavidDeMar는 git log를 변경해야합니다. 원래 이메일을 기록하고 스크립트를 적절히 수정하십시오.
weynhamz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.