Created
March 10, 2012 04:16
-
-
Save milki/2010094 to your computer and use it in GitHub Desktop.
Replace old ff-merges with non-ff merges
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
# xargs -tpa /home/milki/tmp/redo-merges/merges -L 3 /home/milki/tmp/redo-merges/remerge | |
# plan | |
# HEAD points to either the last redone merge or not a merge | |
# if last redone merge, NEW merge base is base of last merge | |
# git rev-parse HEAD^2 last "branch" | |
# else head is NEW merge base | |
# reset to NEW merge base of $2 | |
# branch, cherry-pick from HOLD merge baes to $2~1, return to newmaster | |
# merge branch | |
# rebase to base of $3 | |
# if same OLD merge base, no rebase | |
# else, rebase | |
# $1 previous merge | |
# $2 current merge | |
# $3 next merge | |
# assuming HEAD is result from remerging $1 | |
# origin/master is HEAD for original tree | |
echo "args: $1 $2 $3" | |
REDOFFMERGE=0 | |
git checkout newmaster | |
git branch -f oldmaster | |
#### STEP 1: DETERMINE NEW MERGE BASE #### | |
LASTBASE=`git rev-parse --short $1^2~1` | |
OLDBASE=`git rev-parse --short $2^2~1` | |
if [ $OLDBASE = $LASTBASE ] # same related branch | |
then | |
echo '==Related merge' | |
NEWBASE=`git rev-parse --short oldmaster^2~1` # use the same base as last merge | |
else | |
# Check if bad ff merge at OLDBASE | |
MSG=`git log -n 1 --format=%s $2~1` | |
if echo $MSG | grep --silent split | |
then | |
echo '**FF MERGE DETECTED**' | |
REDOFFMERGE=1 | |
fi | |
echo '==New merge' | |
NEWBASE=`git rev-parse --short oldmaster` # new branch base | |
fi | |
### END STEP 1 | |
### STEP 2 PART 0: RE-MERGE FF BRANCH #### | |
if [ $REDOFFMERGE = 1 ] | |
then | |
echo "Fix ff merge $2~1 onto $NEWBASE" | |
BRANCH=`git log -n 1 $2~1 --stat --name-only | tail -n 2 | sed '/^$/d' | head -n 1 | sed "s/#\(.*\)/\1/"` | |
MSG="Merge branch '$BRANCH'" | |
git checkout -B temp $NEWBASE | |
git cherry-pick $2~1 | |
git checkout newmaster | |
git merge --no-ff -m "$MSG" temp # no-ff merge | |
fi | |
#### STEP 2 PART 1: RE-MERGE BRANCH #### | |
echo "==Fix regular merge $2 onto $NEWBASE" | |
MSG=`git show --format=%s $2` # use same merge message | |
git checkout -B temp $NEWBASE | |
git cherry-pick $2^2 | |
if [[ $? -ne 0 ]] | |
then | |
echo "conflict in cherry-pick" | |
echo "Recover $2" | |
git read-tree $2 | |
git clean -fd | |
git checkout-index -fa | |
git status | |
echo "Using date from $2^2" | |
#CDATE=`git show -s --format=%ci $2^2` | |
#ADATE=`git show -s --format=%ai $2^2` | |
GIT_COMMITTER_DATE="$CDATE" GIT_AUTHOR_DATE="$ADATE" git commit -m "$MSG" | |
fi | |
git checkout newmaster | |
git merge --no-ff -m "$MSG" temp # no-ff merge | |
# Possible conflict | |
if [[ $? -ne 0 ]] | |
then | |
echo "conflict in remerge" | |
echo "Recover $2" | |
git read-tree $2 | |
git clean -fd | |
git checkout-index -fa | |
git status | |
echo "Using date from $2" | |
GIT_COMMITTER_DATE="$CDATE" GIT_AUTHOR_DATE="$ADATE" git commit -m "$MSG" | |
fi | |
### END STEP 2 ### | |
### STEP 3: Rebase to base next merge if unrelated to current merge### | |
if [ -n "$3" ] | |
then | |
NEXTOLDBASE=`git rev-parse --short $3^2~1` | |
NEWMASTER=`git rev-parse --short newmaster` | |
if [ $NEXTOLDBASE != $OLDBASE ] # If next isn't related, rebase | |
then | |
echo "Rebase to next merge-base $NEXTOLDBASE onto $NEWMASTER" | |
git rebase --committer-date-is-author-date -p --onto newmaster $2 $NEXTOLDBASE | |
git branch -f newmaster | |
fi | |
fi | |
### END STEP 3 ### | |
#git log --stat oldmaster..HEAD |
I lost some merges from a single bad merge commit which resulted in non-linear history. When I rebased into this commit, it skipped a couple merges as well as pulled in references to the old repo tree. Manually handling just this part was all that was needed. This script works just fine otherwise. I am done with this!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Replace git show with git rev-parse. Everything looks ok for a while until I start missing some merges. My merge file is probably missing some merge commits.