2014-10-09 5 views
2

커다란 SVN 저장소를 GIT로 마이그레이션했으며 동일한 작성자의 동일한 메시지로 연속 커밋 수가 많습니다.동일한 메시지와 작성자 (전체 저장소)의 연속적인 커밋 autofixup

이제 커밋을 하나의 커밋으로 자동 수정하고 싶습니다.

생각하십니까?

+0

변경 사항을 이전 SVN 저장소로 푸시하기 위해 리포지토리 기능을 유지하고 싶지 않다고 생각합니까? –

+0

@Zeeker 아니 마이그레이션되었습니다 - 그래서 SVN 서버가 내려갑니다 –

+0

나는 현재 내 스마트 폰에있어, 나는 광범위한 답변을 쓸 수 없습니다. 당신은'git filter-branch'에서 스스로를 찾거나 대답을 쓸 때까지 기다릴 수 있습니다. –

답변

0

이것은 내 첫 번째 버전이지만 좀 더 테스트를 필요로하고 내가 훨씬 더 똑똑 할 수있는 확신 :

#!/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은 이미 실험을 시작하고 당신의 방법/상태를 모르는 -이 대답은 아직 받아 들여지지 않았습니다!

2

나는 마침내 인간의 실수로 문제를 해결할 수있었습니다.

여기서 제공하는 스크립트는 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를 사용하여 테스트했습니다.

1

아직 논평 할만한 평판이 충분하지 않습니다.

@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로 변경하는 것이다.