3

I have a Git repository that was converted from Subversion with git svn. I do not have the original Subversion repo anymore and all of the commit messages have a line like this:

git-svn-id: file:///home/jordan/Development/wxSVG/wxsvg-svn/trunk@618 918b0bbe-f86e-4b6f-834e-cb0f658702cb

I want to edit all the commit messages to get rid of this line. I am aware that my Git history will be rewritten and I am okay with that. Manually editing each commit will take a very long time and I would like to know if there is a way to automate this.

I am on a Windows system, but am using a Unix-like shell so Unix/Linux commands are okay. I'm guessing I will need to use the sed command somehow to modify the commit messages, but I have no idea how I would do this.

When I run the git rebase -i <commit-id> command my editor opens & I have to change all pick values to reword. Then I will need to remove the line starting with git-svn-id when the editor opens for each commit.

Is this somehow possible?

Edit: I just found this answer, so my question might be considered a duplicate. I am trying out the suggestions right now and have already found the answer to automatically change "pick" to "reword".

1 Answer 1

3

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .