是否有一个命令来压缩对基地的所有提交?

时间:2017-11-16 10:22:13

标签: git

我有一个hacky shell脚本,用于清理功能分支上的历史记录,当时我正在与那些不了解rebasing如何工作并且有数百个混乱提交和多个合并提交的人一起工作,这意味着它是不可能做单个壁球或修复交互式rebase。

这个脚本基本上会在他们的分支中创建一个单独的压缩提交,而不管他们是如何合并的。

但它真的很hacky,有没有现成的git命令呢?或者是否有更惯用的方式来编写脚本?

#!/bin/bash  
set -e
if [ -n "$(git status -s)" ] ; then
   echo "ERROR: uncommitted changes"
   exit 1
fi
if [ -z "$1" ] ; then
   echo "ERROR: you must provide a base branch"
   exit 1
fi
NAME=`git rev-parse --abbrev-ref HEAD`
CUR=`git rev-parse HEAD`
TO=`git rev-parse $1`
echo "backing up your branch in bak/$CUR"
git checkout -b bak/$CUR
git checkout -b tmp/$CUR
git reset --hard $TO
git merge --squash $CUR
git commit --no-edit
git checkout $NAME
git reset --hard tmp/$CUR
git branch -D tmp/$CUR
echo "created a squash commit against $1 and rewrote your history"

1 个答案:

答案 0 :(得分:2)

  

...是否有现成的git命令执行此操作?

否:就最终提交和分支名称的位置而言,至少需要三个才能完成您的工作:

  1. git branch创建一个新的分支名称,指向由HEAD标识的提交;
  2. git reset --soft将当前分支名称移动到目标提交而不更改索引和工作树;
  3. git commit进行新提交。
  4. 为新提交(由git merge --squash构建的提交)获取所需的日志消息需要其他命令。要让git merge --squash为构建消息,您必须使用git merge --squash或重复其逻辑(检查merge.branchdescmerge.log设置,运行各种Git命令根据这些设置提取适当的字符串。)

      

    或者是否有更惯用的方式来编写脚本?

    好吧,如果您想将它作为贡献脚本提交给Git:那么您可能希望直接使用git-sh-setup和许多较低级别的管道命令,并插入更多错误检查(例如,什么当$1无法正确git rev-parse时脚本应该执行吗?在完全空的存储库中它应该做什么,即使HEAD无效?)。但这会使脚本更加冗长 - 不像rebase代码那样〜2000行怪物:

    $ wc -l git-rebase*sh
         103 git-rebase--am.sh
        1042 git-rebase--interactive.sh
         169 git-rebase--merge.sh
         648 git-rebase.sh
        1962 total
    

    但仍然比现在长很多。

    除此之外:通常,执行此类操作的Git命令根本不会设置备份分支名称。相反,他们依靠Git的 reflogs 作为分支名称,以及保留前一个设置的ORIG_HEAD名称。如果您要省略备份分支并使用git reset --soft && git commit -F $msg_temp_file,您将获得相同的行为 - 但是您必须再次在临时文件中构造合并消息。或者,由于git resetgit merge --squash都设置了ORIG_HEAD,如果您使用git merge --squash创建新合并,则必须使用git update-ref来设置ORIG_HEAD返回正确的值。

    当然,两者都会显着改变可观察行为。