46

我在 github 上有一个 repo,其他人(Bob,为了争论)已经发出了拉取请求。他的代码并不完美,所以我们进行了几轮标记。据我了解,他为每组标记的更改提交并推送他的拉取请求。

所以我的存储库现在看起来像这样:

master: ---o A (Chowlett
           |
           |
pull-req:  o---o---o---o
               B   C   D (all Bob)

提交 SHA 和消息如下:

A:

123456 Good commit <chowlett>

乙:

777ccc Fix the widget bug <bob>

C:

888ddd Review markups <bob>

丁:

999eee Further markups <bob>

我现在很高兴接受这个拉取请求;但我宁愿预标记版本不在我的仓库中。我可以实现以下所有目标吗?如何?

  • 将 B、C 和 D 合并到我的仓库中作为单个提交
  • 生成“Merge pull request #99 into ...”提交
  • 让 github 自动关闭拉取请求
4

5 回答 5

17

请注意,Bob 在进行 GitHub PR 时不必压缩他的提交。
自 2016 年 3 月起,您可以将该操作留给接受 PR 的维护者(您)。

请参阅“ Squash your commits ”及其新文档

这是一个新选项,可让您对通过合并按钮合并的所有拉取请求强制提交压缩。

https://help.github.com/assets/images/help/pull_requests/squash-and-merge.png

于 2016-04-02T18:51:29.543 回答
10

有两个内置的“壁球”功能git。有git merge --squash而且有squash动作git rebase --interactive。前者不保留任何作者或日期信息,只是将一系列提交中的所有更改收集到本地工作副本中。后者很烦人,因为它需要交互。

git squash扩展做你想要的。它将当前 HEAD 重新设置为指定的基础,同时自动压缩其间的提交。它还提供了一个命令行选项,用于在 rebase 不会产生冲突的情况下在最终压扁的提交上设置消息。

hub将其与and一起使用ghi,您也许可以按照以下方式构建一个脚本:

git pull upstream master
hub checkout https://github.com/$user/$repo/pull/$issue
git squash master
rev=$(git rev-parse --short HEAD)
git checkout master
git merge $rev
git commit --amend "Merged pull request #$issue"
git push upstream master
ghi close $issue $user/$repo
ghi comment $issue "Merged as $rev" $user/$repo 
于 2013-05-13T03:24:51.740 回答
9

您可以使用 --squash 选项进行合并

git merge <remote url> <remote branch> --squash

但是,这不会产生合并提交。相反,它将产生一组正常的工作树更改,就像您手动将他的所有更改应用于您的副本一样。然后你会像往常一样提交。

缺点是您在 master 上的历史不会将此提交显示为来自他的分支的合并。看起来就像您自己完成了工作,而不是给 Bob 信用。

于 2012-07-31T17:41:26.367 回答
3

使用 git rebase

一种想法是检查分支并使用迭代变基将所有提交压缩为一个,然后强制推送以更新拉取请求并合并(尽管这项工作的一部分可以委托给 Bob)。

要自动将分支中的所有提交压缩到第一个提交并将其应用于拉取请求,您可以使用以下命令:

$ git checkout pull-req
$ GIT_SEQUENCE_EDITOR='sed -i "2,\$s/^pick/s/g" $1' git rebase -i origin/master
$ git push --force

GIT_SEQUENCE_EDITOR是一个 Git 环境变量,用于为变基提交列表设置临时编辑器。我们将它设置为一个内联脚本,它在除第一行(即模式中的 the )之外的所有行的开头picks(meaning ) 替换单词。传递给脚本的提交列表是一个简单的文本文件。然后 Git 继续进行变基并让您编辑最终的提交消息。squash2,\$sed

此外,使用 git 钩子,您可以或多或少地轻松编辑此最终消息以满足您的需要(例如在压缩的提交消息之间添加一个视觉分隔符)。

使用 git merge --squash

挤压也可以通过git merge --squash. 请参阅此处了解两种方法之间的区别。下面的脚本将使用 merge 命令将分支的提交压缩为单个提交。它还创建分支的备份(以防万一)。

MAINBRANCH="master"    
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)

# update current feature branch with master
git pull origin $MAINBRANCH

# delete existing backup
git branch -D "$CURRENT_BRANCH-backup"

# backup current feature branch and go back
git checkout -b "$CURRENT_BRANCH-backup" && git checkout -

# checkout and update master branch
git checkout $MAINBRANCH && git pull

# create new branch from master
git checkout -b "$CURRENT_BRANCH-squashed"

# set it to track the corresponding feature branch
git branch "$CURRENT_BRANCH-squashed" --set-upstream-to "$CURRENT_BRANCH"

# merge and squash the feature branch into the one created
git merge --squash $CURRENT_BRANCH

# commit the squashed changes
git commit

# force push to the corresponding feature branch
git push -f . HEAD:$CURRENT_BRANCH

# checkout the feature branch
git checkout $CURRENT_BRANCH

# delete the squashed copy
git branch -D "$CURRENT_BRANCH-squashed"
于 2015-12-23T20:56:07.183 回答
1

这对我有用。

  • 我的工作devtools_import_export保持不变。
  • 我对上游/主服务器的拉取请求issue35squashed只有一个提交。
  • 唉,没有记录合并,但提交消息包含所有详细信息。

这是我实际所做的(参见https://github.com/anaran/devtools-snippets/network

git checkout master
git status # all clean
git checkout -B issue35squashed master
git merge --squash devtools_import_export
git status # looks good
git commit # review and commit via emacs
git log --graph --abbrev-commit --stat --pretty --decorate=full --branches
git push --all -v

(我之前使用的尝试git merge --no-ff ...是 inissue35take2并且它的拉取请求包含来自 . 的所有个人提交devtools_import_export。不好。)

于 2013-11-28T13:42:56.893 回答