당신이받은 조언에 결함이 있습니다. 무조건 GIT_AUTHOR_DATE를 설정하면 --env-filter
모든 커밋 날짜가 다시 작성됩니다. 또한 git commit inside 를 사용하는 것은 드문 일 --index-filter
입니다.
여기서 여러 개의 독립적 인 문제를 처리하고 있습니다.
"지금"이외의 날짜 지정
각 커밋에는 작성자 날짜와 커미터 날짜의 두 날짜가 있습니다. 새 커밋을 작성하는 모든 명령에 대해 환경 변수 GIT_AUTHOR_DATE 및 GIT_COMMITTER_DATE를 통해 값을 제공하여 각각을 대체 할 수 있습니다. git-commit (1) 또는 아래의 “날짜 형식”을 참조하십시오 .
Git internal format = <unix timestamp> <time zone offset>, e.g. 1112926393 +0200
RFC 2822 = e.g. Thu, 07 Apr 2005 22:13:13 +0200
ISO 8601 = e.g. 2005-04-07T22:13:13
정상적인 사용 중에 새 커밋을 작성하는 유일한 명령은 git commit 입니다. --date
작성자 날짜를 직접 지정할 수 있는 옵션도 있습니다. 예상 사용량에는 git filter-branch --env-filter
위에서 언급 한 환경 변수도 사용됩니다 (이 옵션은 옵션 이름을 지정한 후 "env"의 일부입니다. git-filter-branch (1)의 "옵션" 및 기본 "배관"명령 git-commit -tree (1) .
단일 참조 기록에 파일 삽입
리포지토리가 매우 간단한 경우 (즉, 태그가없는 단일 분기 만있는 경우) git rebase 를 사용 하여 작업을 수행 할 수 있습니다.
다음 명령에서“A”대신 커밋의 객체 이름 (SHA-1 해시)을 사용하십시오. git commit 을 실행할 때 "date override"메소드 중 하나를 사용하는 것을 잊지 마십시오 .
---A---B---C---o---o---o master
git checkout master
git checkout A~0
git add path/to/file
git commit --date='whenever'
git tag ,new-commit -m'delete me later'
git checkout -
git rebase --onto ,new-commit A
git tag -d ,new-commit
---A---N (was ",new-commit", but we delete the tag)
\
B'---C'---o---o---o master
추가 된 위치에 새 커밋을 작성하는 대신 새 파일을 포함하도록 A를 업데이트하려면 git commit --amend
대신 을 사용하십시오 git commit
. 결과는 다음과 같습니다.
---A'---B'---C'---o---o---o master
위의 내용은 새 커밋의 부모가되어야하는 커밋의 이름을 지정할 수있는 한 작동합니다. 실제로 새로운 루트 커밋 (부모 없음)을 통해 새 파일을 추가하려면 약간 다른 것이 필요합니다.
B---C---o---o---o master
git checkout master
git checkout --orphan new-root
git rm -rf .
git add path/to/file
GIT_AUTHOR_DATE='whenever' git commit
git checkout -
git rebase --root --onto new-root
git branch -d new-root
N (was new-root, but we deleted it)
\
B'---C'---o---o---o master
git checkout --orphan
상대적으로 새롭지 만 (Git 1.7.2), 이전 버전의 Git에서 작동 하는 것과 동일한 작업을 수행하는 다른 방법이 있습니다.
다중 참조 기록에 파일 삽입
저장소가 더 복잡한 경우 (즉, 하나 이상의 참조 (분기, 태그 등)가있는 경우) git filter-branch 를 사용해야 할 것입니다 . git filter-branch를 사용하기 전에 전체 저장소의 백업 사본을 작성해야합니다. 전체 작업 트리 의 간단한 tar 아카이브 (.git 디렉토리 포함)로 충분합니다. git filter-branch 는 백업 참조를 만들지 만 .git
디렉토리를 삭제 하고 백업에서 복원 하여 바로 올바른 필터링에서 복구하는 것이 더 쉬운 경우가 많습니다 .
참고 : 아래 예는 git update-index --add
대신 하위 수준 명령을 사용 git add
합니다. git add를 사용할 수는 있지만 먼저 외부 위치에서 예상 경로로 파일을 복사해야합니다 ( --index-filter
빈 임시 GIT_WORK_TREE에서 명령을 실행).
모든 기존 커밋에 새 파일을 추가하려면 다음을 수행하십시오.
new_file=$(git hash-object -w path/to/file)
git filter-branch \
--index-filter \
'git update-index --add --cacheinfo 100644 '"$new_file"' path/to/file' \
--tag-name-filter cat \
-- --all
git reset --hard
기존 커밋 날짜를 변경해야 할 이유가 없습니다 --env-filter 'GIT_AUTHOR_DATE=…'
. 그것을 사용했다면, 모든 커밋에 대한 날짜를 다시 쓰도록 조건부로 만들 것입니다.
기존의 커밋 (“A”) 후에 커밋에만 새 파일을 표시하려면 다음을 수행하십시오.
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
file_blob=$(git hash-object -w "$file_path")
git filter-branch \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$before_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
히스토리 중간에 삽입 할 새 커밋을 통해 파일을 추가 하려면 git filter-branch 를 사용하기 전에 새 커밋을 생성하고 git filter-branch 에 추가 --parent-filter
해야합니다 .
file_path=path/to/file
before_commit=$(git rev-parse --verify A)
git checkout master
git checkout "$before_commit"
git add "$file_path"
git commit --date='whenever'
new_commit=$(git rev-parse --verify HEAD)
file_blob=$(git rev-parse --verify HEAD:"$file_path")
git checkout -
git filter-branch \
--parent-filter "sed -e s/$before_commit/$new_commit/g" \
--index-filter '
if x=$(git rev-list -1 "$GIT_COMMIT" --not '"$new_commit"') &&
test -n "$x"; then
git update-index --add --cacheinfo 100644 '"$file_blob $file_path"'
fi
' \
--tag-name-filter cat \
-- --all
git reset --hard
로부터의 "고아"방법을 통해 커밋 새 루트를 만들 : 당신은 또한 파일이 처음 커밋 새로운 루트에서 추가로를 준비 할 수 자식 REBASE의 섹션 (캡처 거기에 new_commit
무조건을 사용) --index-filter
, 그리고 --parent-filter
처럼 "sed -e \"s/^$/-p $new_commit/\""
.