non-interactive git squash/rebase all into current branch heads

What is the easiest way to rebase a git repository such that only the heads of current branches remain in tact, and all else is squashed? Preferably a non-interactive solution that I can apply to various repositories.

Background: my repository is too large because it is tracking a lot of legacy code from previous versions. I deleted the branches I am no longer interested in. For the remaining branches, I would like to keep the final versions around for archiving purposes, but clean up all of the intermediate changes.

  • build spring framework source code encounter an error
  • Is there a good git client for Mac OS X that has all the bells and whistles of Conerstone or Versions for Subversion?
  • Why git pull results in thousands of merge conflicts?
  • The Repository is Locked - Error while trying to commit into source control
  • How to list stats of resolved conflicts in a merge commit?
  • Why does checkout sometimes stage a file?
  • Git seems stuck on my old account
  • pip install from bitbucket repo's branch
  • Impact of large number of branches in a git repo?
  • Ignoring directories in earlier commits
  • Git fast-forward merge : why “fast”
  • How do I configure git to use a folder on another network?
  • One Solution collect form web for “non-interactive git squash/rebase all into current branch heads”

    Since I found this question interesting, I wrote a little bash script that does (something like) what you want.

    You can download it as a file (or check out its repo on Github) and find the source below. Here’s a little discussion:


    ./ [-r] [<path to git repo>]
    where -r enables creation of a common root commit and the path let’s you use the script from a different location; if the path is ommitted, the current directory (CWD) is used

    This script’s main task is to transplant currently existing branches, by simply using their latest commit (since Git commits are snapshots of the complete repository, that’s easy).

    If you specify the -r flag, a new empty root commit is created, and all branches are created as direct descendants of that root commit. If you do not specify the flag, every new branch will have its own root (they’ll be orphan branches) and contain exactly one commit each.

    This is done by getting a branch of existing local branches and walking over them; for each branch (call it BR) , the script will:

    • when -r is specified
      • (a) create a new branch from the new common root commit
      • (b) check out the files from BR
    • when -r is not specified
      • (a) check out BR
      • (b) create a new orphan branch from BR
    • (c) commit the files from BR using the commit message from BR
    • (d) delete the old branch BR
    • (e) rename the newly created branch to BR

    If a branch was checked out when the script started (the repo was not in a detached HEAD state), the new version of that branch is checked out at the end; if the repo was on a detached HEAD, the last created branch is left checked out.

    Script source:

    if [ "$1" == "-r" ]; then
        shift 1
    if [ "$#" -eq 1 ]; then
        cd "$1"
    branches=$(git branch --color=never)
    orig_branch=$(echo "$branches" | grep --color=never "^\* " | sed "s/^\* //")
    if [ "$COMMON_ROOT" -eq 1 ]; then
        echo "Creating new (empty) common root commit"
        git checkout --orphan "$TEMP_ROOT_BRANCH" 2> /dev/null
        git rm -r --cached . >/dev/null
        git clean -dfx > /dev/null
        git commit --allow-empty -m "Initial commit" > /dev/null
    echo "$branches" | sed "s/^\* //" | while read branch; do
        echo "Transplanting branch $branch"
        if [ "$COMMON_ROOT" -eq 1 ]; then
            git checkout -b "$newbranch" "$TEMP_ROOT_BRANCH" > /dev/null 2>/dev/null
            git checkout "$branch" -- . > /dev/null 2>/dev/null
            git checkout "$branch" > /dev/null 2>/dev/null
            git checkout --orphan "$newbranch" > /dev/null 2>/dev/null
        git commit -C "$branch" > /dev/null
        git branch -D "$branch" > /dev/null
        git branch -m "$newbranch" "$branch" > /dev/null
    if [ "$COMMON_ROOT" -eq 1 ]; then
        git branch -D "$TEMP_ROOT_BRANCH" > /dev/null
    if [ -n "$orig_branch" ]; then
        git checkout "$orig_branch" 2>/dev/null
    Git Baby is a git and github fan, let's start git clone.