我正在为github上的分叉副本上的开源 repo 做出贡献
我通常只修复我发现的奇怪的错误,所以每隔几个月就会发生一次,同时还会发生许多其他的开发。我在我的 fork 中提出了拉取请求以获取新的更改。
现在它们出现在我的拉取请求中,返回到原始仓库。
如何制作仅包含每个修复提交的干净拉取请求?我曾尝试 git 在本地获取原始仓库并从中进行合并,但我遇到了同样的问题。
tl; dr:从上游/主分支分支。不要向当地的主人承诺。
如果您的分支有本地更改并且您只是与上游合并,那么您仍然会有这些本地更改。当你基于这个合并的 master 提交 PR 时,它将包含那些本地更改。
让我们演示一下。这是与本地更改合并后的样子。
# Your situation after merging with local changes. # D - E - F are new changes from upstream. # 1 - 2 - 3 is your local changes. A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [master]
现在你从 master 创建一个分支并添加一些提交。
A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [master] \ 4 - 5 - 6 [feature]
如果您将 feature 作为 PR 提交,以 upstream/master 作为基础,它将拖入 1 - 2 - 3 以及 4 - 5 - 6,因为它们都包含与 upstream/master 的差异。
这就是为什么要避免直接提交到 master,你不再有新分支的共同基础。相反,在分支中完成所有工作并将它们作为 PR 提交。
最简单和最安全的事情是将您的工作从上游/master 分支而不是 master。那么你的分叉处于什么状态并不重要。
$ git checkout -b feature upstream/master # then make a few commits 4 - 5 - 6 [feature] / A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [master]
如果您有一个现有的 master 分支,请将其 rebase 到 upstream/master。这将重写每个提交,就像您在上游/主控之上编写它一样。可能存在冲突,根据需要修复它们。
# Before with feature based on master. A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [master] \ 4 - 5 - 6 [feature] # Rebase onto upstream/master the commits from master to feature. $ git rebase --onto upstream/master master feature 4A - 5A - 6A [feature] / A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [master] \ 4 - 5 - 6
原来的 4 - 5 - 6 最终会被删除。
要恢复 fork 的 master,请将您的 master 返回master给上游的 master。
master
首先,在您现有的 master 上创建一个新分支以保留任何本地更改。
$ git checkout master $ git branch dev # or whatever you want to call it A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [master] [dev]
现在,您对 master 所做的任何本地更改都将保留在您的dev分支中。您可以随意称呼它,但要避免使用上游已经存在的分支名称。
dev
然后将您的本地主机移动到上游的主机。
$ git checkout master $ git reset --hard upstream/master [master] A - B - C - D - E - F [upstream/master] \ \ 1 - 2 - 3 - M [dev]
Git 中的分支只是指向提交的标签。git reset是您如何随心所欲地移动它们。这会将您的本地主机移动到上游/主机指向的位置。--hard指对暂存区和签出文件(工作副本)做什么。--hard说还要将它们重置为上游/主控。
git reset
--hard
现在你的主人是他们的上游/主人。dev 对 master 进行了本地更改。
最后,将新的本地 master 推送到 origin。既然搬了,就不得不强行。不要使用 –force使用更安全的git push --force-with-lease.
git push --force-with-lease
如果你想更新你的本地 master,只需git pull. Agit pull只是一个git fetch加号git merge。我们将做git pull两个单独的步骤来演示。
git pull
git fetch
git merge
# Fetch new commits, that's G and H. $ git fetch upstream G - H [upstream/master] / A - B - C - D - E - F [master] \ \ 1 - 2 - 3 - M [dev] $ git checkout master $ git merge upstream/master [master] G - H [upstream/master] / A - B - C - D - E - F \ \ 1 - 2 - 3 - M [dev]
由于 master 是 upstream/master 的直接祖先,因此不需要合并提交。Git 将“快进”master 到上游/master。