非交互式git squash / rebase全部进入当前分支头

时间:2013-04-17 18:30:42

标签: git github rebase squash

修改git存储库的最简单方法是什么,只有当前分支的头部保持不变,其他所有部分都被压扁了?最好是我可以应用于各种存储库的非交互式解决方案。

背景:我的存储库太大,因为它正在跟踪以前版本的许多遗留代码。我删除了我不再感兴趣的分支。对于其余的分支,我希望保留最终版本以便存档,但清理所有中间更改。

1 个答案:

答案 0 :(得分:2)

因为我发现这个问题很有趣,所以我写了一个小的bash脚本(你想要的东西)。

您可以download it as a file(或查看its repo on Github)并找到以下来源。这里有一点讨论:

用法:

  

<强> ./start_git_repo_fresh.sh [-r] [<path to git repo>]
  其中-r允许创建公共根提交,而路径允许您使用来自不同位置的脚本;如果省略该路径,则使用当前目录(CWD)

这个脚本的主要任务是移植当前现有的分支,只需使用他们的最新提交(因为Git提交是完整存储库的快照,这很容易)。

如果指定-r标志,则会创建一个新的空根提交,并且所有分支都将创建为该根提交的直接后代。如果你没有指定标志,那么每个新分支都有自己的根(它们将是 orphan 分支)并且每个分支只包含一个提交。

这是通过获得现有本地分支的一个分支并遍历它们来完成的;对于每个分支(称之为BR),脚本将:

  • 指定-r
    • (a)从新的公共根提交
    • 创建一个新分支
    • (b)查看BR
    • 中的文件
  • -r 未指定
    • (a)查看BR
    • (b)从BR
    • 创建一个新的孤儿分支
  • (c)使用BR
  • 中的提交消息从BR提交文件
  • (d)删除旧分支BR
  • (e)将新创建的分支重命名为BR

如果在脚本启​​动时检出分支(repo不在分离的HEAD 状态),则最后检出该分支的新版本;如果回购在一个分离的HEAD上,则最后创建的分支将被检出。


脚本来源:

#!/bin/bash

COMMON_ROOT=0
TEMP_ROOT_BRANCH="NEW_ROOT_COMMIT"

if [ "$1" == "-r" ]; then
    COMMON_ROOT=1
    shift 1
fi

if [ "$#" -eq 1 ]; then
    cd "$1"
fi

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
fi

echo "$branches" | sed "s/^\* //" | while read branch; do
    echo "Transplanting branch $branch"
    newbranch="${branch}_new"
    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
    else
        git checkout "$branch" > /dev/null 2>/dev/null
        git checkout --orphan "$newbranch" > /dev/null 2>/dev/null
    fi
    git commit -C "$branch" > /dev/null
    git branch -D "$branch" > /dev/null
    git branch -m "$newbranch" "$branch" > /dev/null
done

if [ "$COMMON_ROOT" -eq 1 ]; then
    git branch -D "$TEMP_ROOT_BRANCH" > /dev/null
fi

if [ -n "$orig_branch" ]; then
    git checkout "$orig_branch" 2>/dev/null
fi