推送后如何压缩 Bitbucket 上的提交?

How to squash commits on Bitbucket after they have been pushed?

我目前正在与其他多人一起从事一个项目。问题是我们创建了一个现有项目的分支,并且需要将我们在分支过程之后的所有提交压缩为 Bitbucket 上的拉取请求的单个提交。

有没有什么办法(最好使用SourceTree,否则是终端)将已经推送的提交压缩为单个提交,这样 Bitbucket 中所有提交的历史也只是那个提交加上提交在我们分叉项目之前哪些已经存在?

以一个简单的项目为例,只有一个 master 分支中有几个文件。

...we created a fork of an existed project and need to squash all our commits from after the forking process to a single commit for a pull-request on Bitbucket

请注意,拉取请求不需要单个提交。一堆提交可以构成一个拉取请求。

Is there any way (preferably using SourceTree, otherwise terminal) to squash already pushed commits to a single commit?

是的,您可以使用交互式变基 git rebase -i

然后您可以标记要压缩的提交(按照编辑器中出现的 on-screen 说明进行操作),然后在完成后写一条新的提交消息(在每个之后使用 git rebase --continue提交你已经完成的工作)。

如果您已经推送了它们,则需要使用 -f 选项强制推送。请注意,这是不受欢迎的,因为任何其他取消这些更改的人都必须跳过可能与 new 历史记录重新同步的环节。

在 SourceTree 中可能有一种方法。

Further reading.

使用git rebase!

Bitbucket use the Git software.

alex said it already in his post: Use the git rebase -i ourbranchname command!


命令

在终端、命令提示符或您的 cmd 中使用这些命令:

  1. git rebase -i yourbranchname
  2. 编辑器程序中的文件将自动打开。
  3. 将所有提交从“pick”更改为“fixup”,但一个提交必须具有“pick”!
  4. 保存文件并关闭。
  5. git push -f origin yourbranchname

有用的资源

使用 SourceTree 可以轻松实现变基,在 sourcetree 中 select 您的工作基于的提交,然后按鼠标右键。

然后会弹出一个菜单,select "interactively rebase children of "

这将打开一个屏幕,我们可以在其中 select 如何处理每次提交。由于我们想将每个提交压缩在一起,因此我们单击顶部提交和 select 屏幕底部的按钮 "Squash with previous"。 Sourcetree 将更新顶部屏幕以响应您所做的操作,以便您可以看到它正在执行您想要的操作。

之前:

之后:

通常,当你把它们压在一起时,你还想改变提交的消息,双击消息来改变它。如果您已完成更改,请按右下角的 "ok"。 Source Tree 现在将为您重新设置历史记录。

完成结果:

现在您可以强制将您的分支推送到您自己的另一个项目的分支,并尝试发出另一个拉取请求。

找到已发布答案的一个很好的摘要。这个更清楚一点: squash pushed commits。 它将需要在创建分叉时创建第二个分支。第二个分支可以根据需要向远程服务器推送尽可能多的内容。

  1. 创建一个将被压缩的新个人分支。

    # Start with the existing personal branch that contains all of your commits.
    $ git checkout {ExistingBranchName}
    # Create a new personal branch that will be squashed.
    $ git checkout -b {BranchName}
    
  2. 确定您的个人分支与现有 CEF 分支不同的第一个提交。

    # Replace {BranchName} with your new branch name.
    # Replace "master" with a different CEF branch as appropriate
    # (e.g. "2272", "2171", etc).
    $ git merge-base {BranchName} master
    
  3. 使用从第 2 步返回的提交哈希启动交互式变基。

    $ git rebase --interactive {hash}
    

    这将启动一个文本编辑器,其中包含您个人分支中所有提交的列表。它应该看起来像这样:

    pick 59d2a23 Initial implementation
    pick 752ae4c Add more features
    pick cd302a3 Fix something
    pick 5410de3 Fix something else
    
  4. 将除第一行以外的所有内容更改为 squash 而不是 pick。内容现在应如下所示:

    pick 59d2a23 Initial implementation
    squash 752ae4c Add more features
    squash cd302a3 Fix something
    squash 5410de3 Fix something else
    
  5. 保存更改并关闭文件(可以通过按 esc 并键入::wq.

    现在将打开一个新文件,其中包含来自所有提交的提交消息。重写提交消息然后保存更改并关闭文件。

  6. 将修改推送到您的个人远程存储库。

    # If the branch has already been pushed to the remote repository
    # you will need to add the  `--force` argument.
    git push origin {BranchName}
    # or git push origin {BranchName} --force
    

有一个更简单的方法。

如果您绝对确定没有人会使用该特定分支,您可以执行以下操作:

  1. 创建一个包含每个人提交的本地分支。
  2. git 登录本地分支以确定第一个分支提交之前的非分支提交的哈希值。
  3. 做:git reset --soft <hash>
  4. 执行:git 提交以创建您想要的单个提交消息。
  5. 执行:git rebase -i 将您的本地分支移动到 master 的顶端。
  6. 修复任何合并冲突。
  7. git 将您的更改推送到用于 PR 的远程分支。如果它已经存在,则使用 -f 强制推送。

您可以使用此脚本压缩当前分支的所有提交以及最终提交消息。

 #!/bin/sh 

 # brief: This script should be run from within your git repo. You need to have   your feature branch

 # checked out. This will squash all the commits on your feature branch (assuming you 

 # branched from master). Then you can just use the github PR UI to merge the PR in. You need to have 
 # feature branch checked out when you run this script (git checkout feature branch).

 # usage: git-helper-squash-all-commits <final commit messsage ex: "reorganizing directory structure"

 # example: git-helper-squash-all-commits "reorganizing directory structure"

 set -ex

 FINAL_COMMIT_MESSAGE=

 BRANCH_YOU_BRANCHED_FROM=master

 CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`

 COMMIT_HASH=`git merge-base HEAD $BRANCH_YOU_BRANCHED_FROM`

 git reset --soft $COMMIT_HASH

 git commit -am "$FINAL_COMMIT_MESSAGE"

 git push origin $CURRENT_BRANCH --force