2013-04-17 38 views
1

将git存储库重新绑定成最简单的方法是什么?只有当前分支的头部保持机密,其他所有分支都被压扁?最好是我可以应用于各种存储库的非交互式解决方案。非交互式的git squash/rebase全部转化为当前分支头

背景:我的存储库太大了,因为它正在跟踪以前版本中的很多遗留代码。我删除了我不再感兴趣的分支机构。对于其余分支机构,我想保留最终版本用于归档目的,但要清理所有中间变更。

回答

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

这是通过获得一个现有的本地分支分支并走过它们;每个分支(称之为BR),脚本将:

  • -r指定
    • (一)创建新的共同的根新枝犯
    • (二)检查出从BR
  • 文件时指定
    -r
    • (a)中检查出BR
    • (b)中创建从BR一个新的孤儿分支
  • (c)使用从BR提交消息从BR提交文件
  • (d)删除老枝BR
  • (五)重命名新创建的分支BR

如果分支在脚本启动时签出(回购不在分离的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