git 只对 github 拉取请求进行一次“正确”提交
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11396069/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Squash to only one "proper" commit for github pull request
提问by Chowlett
I have a repo on github which someone else (Bob, for the sake of argument) has issued a pull request for. His code's not perfect, so we go through a few rounds of markups. As I understand it, he commits and pushes to his pull-request for each set of marked up changes.
我在 github 上有一个 repo,其他人(为了争论,Bob)已经向它发出了拉取请求。他的代码并不完美,因此我们进行了几轮标记。据我了解,他为每组标记的更改提交并推送他的拉取请求。
So my repository now looks like this:
所以我的存储库现在看起来像这样:
master: ---o A (Chowlett
|
|
pull-req: o---o---o---o
B C D (all Bob)
Commit SHAs and msgs are as follows:
提交 SHA 和 msgs 如下:
A:
A:
123456 Good commit <chowlett>
B:
乙:
777ccc Fix the widget bug <bob>
C:
C:
888ddd Review markups <bob>
D:
乙:
999eee Further markups <bob>
I'm now happy to accept this pull request; but I'd rather the pre-markup versions weren't in my repo. Can I achieve all of the following; and how?
我现在很高兴接受这个拉取请求;但我宁愿预标记版本不在我的回购中。我能否实现以下所有目标;如何?
- Merge B, C & D into my repo as a single commit
- Generate the "Merge pull request #99 into ..." commit as well
- Have github automatically close the pull request
- 将 B、C 和 D 作为单个提交合并到我的仓库中
- 生成“Merge pull request #99 into ...”提交
- 让github自动关闭pull request
回答by VonC
Note that Bob doesn't have to squash his commits when he is making a GitHub PR.
Since March 2016, you can leave that operation to the maintainer (you) accepting your PR.
请注意,Bob 在进行 GitHub PR 时不必压缩他的提交。
自 2016 年 3 月起,您可以将该操作留给接受您的 PR 的维护者(您)。
See "Squash your commits" and its new documentation
This is a new option which lets you force commit squashing on all pull requests merged via the merge button.
这是一个新选项,可让您对通过合并按钮合并的所有拉取请求强制提交压缩。
回答by joeln
There are two 'squash' functions inbuilt into git
. There is git merge --squash
and there's the squash
action in git rebase --interactive
. The former doesn't retain any author or date information, just collecting all changes from a series of commits into the local working copy. The latter is annoying because it requires interaction.
内置了两个“挤压”函数git
。有git merge --squash
而且有squash
行动git rebase --interactive
。前者不保留任何作者或日期信息,只是将一系列提交的所有更改收集到本地工作副本中。后者很烦人,因为它需要交互。
The git squash
extensiondoes what you want. It rebases the current HEAD onto a specified base while automatically squashing the commits in between. It also provides a command-line option to set the message on the final squashed commit in cases where the rebase doesn't create conflicts.
该git squash
扩展程序可以满足您的需求。它将当前 HEAD 重新绑定到指定的基数,同时自动压缩其间的提交。它还提供了一个命令行选项,用于在 rebase 不会产生冲突的情况下在最终压缩提交上设置消息。
Throwing this together with hub
and ghi
, you might be able to construct a script along these lines:
将它与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
回答by D-Rock
You can use the --squash option for merge
您可以使用 --squash 选项进行合并
git merge <remote url> <remote branch> --squash
This will however not produce a merge commit. It will instead produce a normal set of working tree changes as if you manually applied all of his changes to your copy. You would then commit like normal.
然而,这不会产生合并提交。相反,它将产生一组正常的工作树更改,就像您手动将他的所有更改应用到您的副本一样。然后你会像往常一样提交。
The downside will be that your history on master will not show this commit as a merge from his branch. It will just look like you did the work yourself and not give Bob credit.
缺点是您在 master 上的历史记录不会将此提交显示为来自他的分支的合并。看起来就像你自己完成了这项工作,而不是给鲍勃功劳。
回答by Samir Aguiar
Using git rebase
使用 git rebase
One idea would be to checkout the branch and squash all commits into one using the iteractive rebase, then force push to update the pull request and merge (though part of this work could be delegated to Bob).
一种想法是使用迭代 rebase 检出分支并将所有提交压缩为一个,然后强制推送更新拉取请求并合并(尽管这项工作的一部分可以委托给 Bob)。
To automatically squash all commits from a branch into the first one and apply this to the pull request, you can use the following commands:
要自动将分支中的所有提交压缩到第一个分支并将其应用于拉取请求,您可以使用以下命令:
$ git checkout pull-req
$ GIT_SEQUENCE_EDITOR='sed -i "2,$s/^pick/s/g" ' git rebase -i origin/master
$ git push --force
GIT_SEQUENCE_EDITORis a Git environment variable to set a temporary editor for the rebase commit list. We set it to a inline script which replaces the word pick
by s
(meaning squash
) in the beginning of all lines except the first (that's the 2,\$
in the sed
pattern). The commit list that gets passed to the script is a simple text file. Git then proceeds with the rebase and lets you edit the final commit message.
GIT_SEQUENCE_EDITOR是一个 Git 环境变量,用于为 rebase 提交列表设置临时编辑器。我们将其设置为内联脚本它取代了字pick
由s
(意squash
),在除第一个所有行(这是一开始2,\$
的sed
模式)。传递给脚本的提交列表是一个简单的文本文件。然后 Git 继续执行 rebase 并让您编辑最终的提交消息。
Also, with a git hook you could then more or less easily edit this final message to suit your needs (say add a visual separator between the squashed commits' messages).
此外,使用 git hook,您可以或多或少地轻松编辑此最终消息以满足您的需要(例如在压扁的提交消息之间添加视觉分隔符)。
Using git merge --squash
使用 git merge --squash
Squashing is also possible through git merge --squash
. See herefor the difference between the two methods. The script bellow would squash the commits of a branch into a single commit using the merge command. It also creates a backup of the branch (just in case).
也可以通过 进行挤压git merge --squash
。请参阅此处了解两种方法之间的区别。下面的脚本将使用合并命令将分支的提交压缩为单个提交。它还创建了分支的备份(以防万一)。
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"
回答by stackunderflow
This worked out for me.
这对我有用。
- My work on
devtools_import_export
stays intact. - My pull request for
issue35squashed
to upstream/master has only one commit. - Alas, the merge isn't recorded, but the commit message has all details.
- 我的工作
devtools_import_export
保持不变。 - 我
issue35squashed
对上游/主控的拉取请求只有一次提交。 - 唉,合并没有被记录下来,但提交消息有所有的细节。
Here is what I actually did (see https://github.com/anaran/devtools-snippets/network)
这是我实际所做的(参见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
(My earlier attempt using git merge --no-ff ...
is in issue35take2
and a pull request for it contains all the individual commits from devtools_import_export
. No good.)
(我之前尝试使用的git merge --no-ff ...
是 inissue35take2
并且对它的拉取请求包含来自devtools_import_export
. 的所有个人提交。不好。)