如何将整个存储库压缩到第一次提交?

我可以将base转换为第一次提交,但这将留给我2次提交。 有没有办法在第一个提交之前引用这个提交?


当前回答

对我来说是这样的: 我总共提交了4次,并使用了交互式rebase:

git rebase -i HEAD~3

第一次提交仍然存在,我最近进行了3次提交。

如果你卡在接下来出现的编辑器中,你会看到smth:

pick fda59df commit 1
pick x536897 commit 2
pick c01a668 commit 3

你必须先做出承诺,然后把其他人推到上面。你需要的是:

pick fda59df commit 1
squash x536897 commit 2
squash c01a668 commit 3

为此,使用INSERT键更改“插入”和“编辑”模式。

使用:wq保存并退出编辑器。如果您的光标位于这些提交行之间或其他位置,请按ESC并重试。

结果我有两次提交:第一次仍然存在,第二次带有“这是3次提交的组合”的消息。

详情请点击此处: https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit

其他回答

这个答案改进了上面的几个(请投票),假设除了创建一个提交(no-parents - no-history),你还想保留该提交的所有提交数据:

作者(姓名及邮箱) 撰写日期 提交人(姓名及邮箱) 提交日期 提交日志消息

当然,新的/single提交的commit- sha会改变,因为它代表了一个新的(非)历史,变成了一个无父/根提交。

这可以通过读取git日志并为git提交树设置一些变量来实现。假设你想在一个新的分支one-commit中从master创建一个单独的提交,保留上面的commit-data:

git checkout -b one-commit master ## create new branch to reset
git reset --hard \
$(eval "$(git log master -n1 --format='\
COMMIT_MESSAGE="%B" \
GIT_AUTHOR_NAME="%an" \
GIT_AUTHOR_EMAIL="%ae" \
GIT_AUTHOR_DATE="%ad" \
GIT_COMMITTER_NAME="%cn" \
GIT_COMMITTER_EMAIL="%ce" \
GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
')

一个衬套

你可以直接从HEAD创建一个squash-all commit,完全不需要rebase,只需要运行:

git reset $(git commit-tree HEAD^{tree} -m "A new start")

在~/.gitconfig中创建别名

[alias]
  squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} \"$@\");};f"

然后只要运行:git squash-all -m“一个全新的开始”

注意:要么从标准输入提供提交消息,要么通过-m/-F选项,就像git commit命令一样。参见git-commit-tree手册。

或者,您也可以使用以下命令创建别名:

git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} "$@");};f'

解释

create a single commit via git commit-tree What git commit-tree HEAD^{tree} -m "A new start" does is: Creates a new commit object based on the provided tree object and emits the new commit object id on stdout. The log message is read from the standard input, unless -m or -F options are given. The expression HEAD^{tree} represents the tree object corresponding to HEAD, namely the tip of your current branch. see Tree-Objects and Commit-Objects. reset the current branch to the new commit Then git reset simply reset the current branch to the newly created commit object. This way, nothing in the workspace is touched, nor there's need for rebase/squash, which makes it really fast. And the time needed is irrelevant to the repository size or history depth.


变体:项目模板中的新回购

这对于在新项目中使用另一个存储库作为模板/原型/种子/框架创建“初始提交”非常有用。例如:

cd my-new-project
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")

这避免了将模板回购作为远程(源或其他)添加,并将模板回购的历史记录折叠到初始提交中。

首先,使用git rebase -interactive将所有提交压缩成一个提交。现在就剩下两个壁球提交了。要做到这一点,请阅读任何一本

如何合并Git存储库的前两次提交? Git:如何压缩前两次提交?

用嫁接压扁

添加一个文件。git/info/grafts,把你想要成为根的提交散列放在那里

Git日志现在将从该提交开始

要让它“真实”运行git filter-branch

从git 1.6.2开始,你可以使用git rebase——root -i

对于除第一次提交外的每个提交,将pick更改为squash。