jptsetung
jptsetung

Reputation: 9156

Git, how to automatize history collapse with rebase

I use a combination of these 2 articles to collapse my Git history : Collapsing a git repository's history and Combine the first two commits of a Git repository?

This is the result

git rebase -i THE_SHA_1_OF_FIRST_COMMIT
# change "pick" into "squash" for all commits except first one
# :wq (if your editor is vi)
git rebase -i THE_SHA_1_OF_FIRST_COMMIT
# change "pick" into "edit"
# :wq (if your editor is vi)
git reset --soft HEAD^
git commit --amend
git rebase --continue
# garbage collect
git reflog expire --expire=1.minute refs/heads/master
git fsck --unreachable
git prune
git gc

This work great but as I use this quite often, I wish to automatize this in a script. The problem is some commands like "git rebase -i" open a file to edit and I have to do it manually (same problem for "git commit --amend"). Is there a way to automatize this process? I'm not asking for a solution ready to use, just the idea.

Upvotes: 4

Views: 731

Answers (2)

jptsetung
jptsetung

Reputation: 9156

I got it working using the command git config --global core.editor to send the list of commits to a script instead of the default editor. Feels a bit dirty (and maybe not optimized) but it works, and now I can collapse the history of my repositories within one command!

You need 2 bash scripts.

First script replacepick.sh, the script that's used instead of the editor. Parses all lines and replace 'pick' by (argument 1) from line #(argument 2) in file (argument 3).

#!/bin/bash

# ./replacepick.sh replacewith fromindex filename

REPLACEWITH=$1
FROMINDEX=$2
FILE=$3


echo $FILE

mathccount=0

if [ -f $FILE ]
then
    OUTPUT=$FILE.tmp
    echo "" > $OUTPUT
    cat $FILE | while read line
    do
        if [[ "$line" == pick* ]]
        then
            matchcount=$(($matchcount + 1))
            if [ $matchcount -gt $FROMINDEX ]
            then
                echo ${line/pick/$REPLACEWITH} >> $OUTPUT
            else
                echo $line >> $OUTPUT
            fi
        else
            echo $line >> $OUTPUT
        fi
    done
    newfilecontent=`cat $OUTPUT`
    echo $newfilecontent > $FILE
fi

And the bash script collapsehistory.sh calling the git commands :

#!/bin/bash

# Collapse all commits on second commit
`git config --global core.editor "/Users/macbook/Documents/GitTests/replacepick.sh squash 1"`
`git rebase -i $1`
`git rebase --continue`

# Collapse 2 commits on one
`git config --global core.editor "/Users/macbook/Documents/GitTests/replacepick.sh edit 0"`
`git rebase -i $1`

`git reset --soft HEAD^`
`git config --global core.editor "cat"`
`git commit --amend`
`git rebase --continue`

# garbage collect
`git reflog expire --expire=1.minute refs/heads/master`
`git fsck --unreachable`
`git prune`
`git gc`

# restore your favorite editor
`git config --global core.editor "vi"`

Then you execute /path/to/historycollapse.sh SHA1_OF_FIRST_COMMIT and you're done! Hope it helps some of you too.

Upvotes: 2

patthoyts
patthoyts

Reputation: 33193

You should look at git merge --squash which will merge and squash all the commits onto your current branch without actually making a commit. You can then check and commit.

Upvotes: 1

Related Questions