커다란 SVN 저장소를 GIT로 마이그레이션했으며 동일한 작성자의 동일한 메시지로 연속 커밋 수가 많습니다.동일한 메시지와 작성자 (전체 저장소)의 연속적인 커밋 autofixup
이제 커밋을 하나의 커밋으로 자동 수정하고 싶습니다.
생각하십니까?
커다란 SVN 저장소를 GIT로 마이그레이션했으며 동일한 작성자의 동일한 메시지로 연속 커밋 수가 많습니다.동일한 메시지와 작성자 (전체 저장소)의 연속적인 커밋 autofixup
이제 커밋을 하나의 커밋으로 자동 수정하고 싶습니다.
생각하십니까?
이것은 내 첫 번째 버전이지만 좀 더 테스트를 필요로하고 내가 훨씬 더 똑똑 할 수있는 확신 :
#!/bin/bash
git filter-branch --force --prune-empty --tree-filter 'GIT_PARANT=$(git log -n 2 $GIT_COMMIT --pretty=format:"%h" | wc -l); if [ "$GIT_PARANT" = "1" ]; then GIT_SUBJECT=$(git log -n 1 $GIT_COMMIT --pretty=format:"%s" | sed -e "s/ \\+/ /g" -e "s/^ *//" -e "s/ *\$//"); GIT_LAST_SUBJECT=$(git log -n 1 $GIT_COMMIT~1 --pretty=format:"%s" | sed -e "s/ \\+/ /g" -e "s/^ *//" -e "s/ *\$//"); GIT_LAST_AUTHOR=$(git log -n 1 $GIT_COMMIT~1 --pretty=format:"%an <%ae>"); GIT_LAST_COMMITTER=$(git log -n 1 $GIT_COMMIT~1 --pretty=format:"%cn <%ce>"); echo "\n - test subject: $GIT_SUBJECT <-> $GIT_LAST_SUBJECT\n - test author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> <-> $GIT_LAST_AUTHOR\n - test committer: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> <-> $GIT_LAST_COMMITTER"; if [ "$GIT_SUBJECT" = "$GIT_LAST_SUBJECT" ] && [ "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" = "$GIT_LAST_AUTHOR" ] && [ "$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = "$GIT_LAST_COMMITTER" ]; then git reset $GIT_COMMIT~1; else echo "...pick"; fi; else echo "\n...pick"; fi' --tag-name-filter cat -- --all
@Zeeker은 이미 실험을 시작하고 당신의 방법/상태를 모르는 -이 대답은 아직 받아 들여지지 않았습니다!
나는 마침내 인간의 실수로 문제를 해결할 수있었습니다.
여기서 제공하는 스크립트는 bash 용으로 작성되었지만 실험 결과에서 볼 수 있듯이 이는 문제가되지 않습니다. 스크립트는 현재 있는지 확인합니다
git filter-branch --commit-filter "$(cat /path/to/the/script)"
: 당신은 통해 스크립트를 실행할 수 있습니다
#!/bin/bash
author="$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>"
msg="$(cat)"
tree="$1"
parents=()
shift
while getopts ":p:" opt; do
case $opt in
p)
parents=(${parents[*]} $OPTARG)
;;
?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
create_parents_option() {
parentsstring=""
for parent in [email protected]; do
parentsstring+="-p $parent "
done
echo "$parentsstring"
}
get_msg() {
git log -1 --format="%B" $1
}
get_author() {
git log -1 --format="%aN <%aE>" $1
}
squash_commit() {
if [ "x$author" == "x$(get_author $1)" ] && [ "x$msg" == "x$(get_msg $1)" ]; then
git read-tree -m --aggressive ${1}^{tree} $tree >/dev/null
tree=$(git write-tree)
parents=($(git log --format=%P -1 $1))
fi
}
if [[ ${#parents[@]} == 1 ]]; then
squash_commit ${parents[0]}
fi
git commit-tree $tree $(create_parents_option ${parents[@]}) -m "$msg"
:
이
내가 아래에 상세하게 설명 할 것 스크립트입니다 커밋은 이전과 같은 작성자와 동일한 메시지로 커밋되었습니다.그럴 경우 현재 커밋의 트리를 git read-tree -m
을 사용하기 전에 커밋 변경과 병합하고 주어진 트리를 병합하고 그 결과를 인덱스에 씁니다.
git write-tree
은 인덱스의 병합 된 결과에서 새 트리를 생성하는 데 사용됩니다.
그런 다음 스크립트는 현재 커밋의 부모를 병합 된 커밋의 부모 부모로 설정하여이 커밋을 효과적으로 "제거"합니다.
더 궁금한 점이 있으면 기꺼이 도와 드리겠습니다. 이 일을하는 것은 재미있었습니다!
편집 :이 스크립트는 Windows 7에서 msysgit 버전 1.9.2를 사용하여 테스트했습니다.
아직 논평 할만한 평판이 충분하지 않습니다.
@Zeeker 내가 당신에게 스크립트를 시도했지만이 오류 받고 있어요 :
git filter-branch --commit-filter "$(cat filter.sh)"
이 자식 1.7.10.4
실행 : 당신이 말한 것처럼 실행
Rewrite 34eb354e01107e111ee0f0a332bc78455bb41bba (1/5)git commit-tree: 52: Syntax error: "(" unexpected
could not write rewritten commit
을 어떤 아이디어?
debian/bin/sh의 edit :은 대시로 가리키고 bash는 가리키지 않습니다.커밋 필터는 대시로 실행되어 이러한 오류를 발생시킵니다. Dash는이 배열 구문을 처리 할 수 없습니다. 내가 찾은 유일한 해결책은/bin/sh의 symlink를 대시에서 bash로 변경하는 것이다.
변경 사항을 이전 SVN 저장소로 푸시하기 위해 리포지토리 기능을 유지하고 싶지 않다고 생각합니까? –
@Zeeker 아니 마이그레이션되었습니다 - 그래서 SVN 서버가 내려갑니다 –
나는 현재 내 스마트 폰에있어, 나는 광범위한 답변을 쓸 수 없습니다. 당신은'git filter-branch'에서 스스로를 찾거나 대답을 쓸 때까지 기다릴 수 있습니다. –