The answer found here helped me to find a solution:
The first part of my question was how to automatically change the pick
keyword to reword
so that all commits would be edited. the answer was to set the sequence editor in git config
to the command sed -i s/pick/reword/
. This can be done for a single command using the -c
switch:
git -c sequence.editor='sed -i s/pick/reword/' rebase -i <commit-id>
For the second part, of actually changing all the commit messages, it turns out that I do not need to worry about the first part. I just need to use the -x
switch to execute a git command for each commit message to be edited. For this, instead of setting the sequence editor, the core editor needs to be set with -c core.editor='<sed-command>'
:
git rebase <commit-id> -x "git -c core.editor='sed -i s/git-svn-id.*//g' commit --amend"
Additional Information for Preserving Committer Name, Email, & Date
**Edit:** The committer name, email, & date can be copied from author information for each commit with the following command:
git rebase <commit-id> -x "GIT_COMMITTER_DATE=\"$(git log -1 --pretty=format:%ad)\" git -c user.name='$(git log -1 --pretty=format:%an)' -c user.email='$(git log -1 --pretty=format:%ae)' -c core.editor='sed -i s/git-svn-id.*//g' commit --amend"
**Edit:** The previous edit had an error in it. The committer date was not being set correctly. In order to use the correct date for each individual commit, add `cat .git/rebase-merge/orig-head`
to the end of the `GIT_COMMITTER_DATE` command:
git rebase <commit-id> -x "GIT_COMMITTER_DATE=\"$(git log -1 --pretty=format:%ad `cat .git/rebase-merge/orig-head`)\" git -c user.name='$(git log -1 --pretty=format:%an)' -c user.email='$(git log -1 --pretty=format:%ae)' -c core.editor='sed -i s/git-svn-id.*//g' commit --amend"
This will retrieve the date using the hash from the original commit instead of only using the date from the most recent commit.
Edit: I was having trouble preserving the committer date for each commit using the GIT_COMMITTER_DATE
environment variable with rebase. So after some playing around I was able to do what I wanted with git cherry-pick
. This may not be the best method to achieve this, but it worked for me.
First I made a list of all commit hashes in reverse order (note that <start-commit>
is not included:
git log --reverse --format="%H" <start-commit>...<end-commit> > ../hashes.txt
Then I used the following loop command to add each commit individually while preserving committer name, email, & date (if you do not need to modify commit message omit -c core.editor='<editor-command>'
& add --no-edit
option to commit command):
for COMMIT in $(cat ../hashes.txt); do \
git cherry-pick $COMMIT && \
GIT_COMMITTER_DATE="$(git log -1 --format=%cd $COMMIT)" git -c user.name="$(git log -1 --format=%cn $COMMIT)" -c user.email="$(git log -1 --format=%ce $COMMIT)" -c core.editor='sed -i s/git-svn-id.*//g' commit --amend; \
if [ "$?" -ne "0" ]; then break; fi; done
The if [ "$?" -ne "0" ]; then break; fi;
code forces the loop to exit if the cherry pick fails. If this occurs, you will need to remove all hashes from the hashes.txt
file before you can continue. If it stops with a cherry pick in progress, you will need to resolve any conflicts then use git cherry-pick continue
. Then you will need to amend the commit manually to set committer name, email, & date before continuing.