如何将整个存储库压缩到第一次提交?
我可以将base转换为第一次提交,但这将留给我2次提交。 有没有办法在第一个提交之前引用这个提交?
如何将整个存储库压缩到第一次提交?
我可以将base转换为第一次提交,但这将留给我2次提交。 有没有办法在第一个提交之前引用这个提交?
当前回答
以下是我最后是如何做到这一点的,以防其他人也能做到:
记住,做这样的事情总是有风险的,在开始之前创建一个保存分支从来都不是一个坏主意。
从日志开始
git log --oneline
滚动到第一次提交,复制SHA
git reset --soft <#sha#>
将<#sha#>替换为从日志中复制的sha
git status
确保所有内容都是绿色的,否则运行git add -A
git commit --amend
将当前所有更改修改为当前首次提交
现在强制推这个分支,它会覆盖那里的内容。
其他回答
当我从git存储库恢复模板时,我通常会压缩整个树,以获得更干净的历史记录,并确保合法合规。我的工作流程是这样的:
git clone https://git.invalid/my-awesome-template.git my-awesome-foo
cd !$
git branch -M master my-awesome-template/master
git checkout --orphan master
git rm -rf /
git commit --allow-empty --allow-empty-message -m 'Initial commit'
git merge --squash --allow-unrelated-histories my-awesome-template/master
git commit
git branch -D my-awesome-template/master
# you can now `drop' that "Initial commit":
git rebase -i --root
这将把整个历史记录压缩到一个大的提交消息中。
在这个例子中:
Master是工作分支 My-awesome-template /master是一个中间分支
一个衬套
你可以直接从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")
这避免了将模板回购作为远程(源或其他)添加,并将模板回购的历史记录折叠到初始提交中。
这个答案改进了上面的几个(请投票),假设除了创建一个提交(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
')
我读过一些关于移植的东西,但从来没有深入研究过。
不管怎样,你可以手动压缩最后2次提交,就像这样:
git reset HEAD~1
git add -A
git commit --amend
我通常是这样做的:
Make sure everything is committed, and write down the latest commit id in case something goes wrong, or create a separate branch as the backup Run git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD` to reset your head to the first commit, but leave your index unchanged. All changes since the first commit will now appear ready to be committed. Run git commit --amend -m "initial commit" to amend your commit to the first commit and change the commit message, or if you want to keep the existing commit message, you can run git commit --amend --no-edit Run git push -f to force push your changes