将更改从 "master" 转移到我的分支

Transfer changes from "master" to my branch

我的仓库中的网络图如下:

M--------------M
|              ↑
├-->1---1---1--┘
|
└-->2---2

其中:Mmaster 上的推送提交,1branch-1 上的推送提交,2 是 [=19= 上的推送提交].

如您所见,来自 branch-1 的提交被推送,请求 "pull request" 并合并到 master.

我在 branch-2 并且在我的任务下工作。

我需要大师的源代码才能完成它们。

第一个问题:如何将源代码从master转移到我的branch-2

我在考虑:

git fetch origin
git rebase origin/master

或:

git pull origin --rebase master

第二个问题:如果我在 branch-2 上推送第二次提交后有本地更改,我想做与上面相同的事情,我该怎么办?

您尝试执行的操作最好通过合并或变基来完成。

推和拉只是您尝试做的事情的附带结果。他们只是确保你本地的 repo 副本与远程的同步。所有实际操作都纯粹在本地完成。如果您的分支上有本地提交,它们将被使用。

要让 master 进入你的分支,你可以变基到 master,或者合并 master。如果你在个人分支上工作并且你有权强制推送非快进提交,变基将保留你的历史清洁工:

git rebase master
git push -f

另一方面,如果您正在协同工作,或者没有强制推送权限,请使用合并:

git merge master
git push

以上两个操作都假设您在您感兴趣的分支上。在这两种情况下,远程分支都不会以任何方式进入操作的第一部分。不同的推送选项只是考虑到你的远程是否可以在更改后从本地分支快速转发。

更新 - 我忘了回答第二个问题


第一个问题

您可以将 master 合并到您的分支,rebase 您的分支合并到 master 上的稍后提交,或者 cherry-pick 引入您需要的更改的提交。要做什么取决于您(和您的团队,如果适用)想要使用哪种工作流程。

merge 的优点是它不会重写任何历史记录,也不会重复任何提交。在某些方面,这是最简单的操作,但它确实创造了许多人认为更复杂的历史。 (没有人 objective 回答什么样的历史是 "better";这取决于你想如何使用历史。)如果你决定合并你可以做类似

git checkout branch-2
git merge master

这假定您的本地主机是最新的。如果不是,你可以更新它,或者做

git fetch
git checkout branch-2
git merge origin/master

默认情况下,pull是“fetchmerge”的快捷方式,因此您也可以

git checkout branch-2
git pull origin/master

就我个人而言,我通常不会这样使用 pull;我仅在从其自己的上游更新分支时才使用它。但它仍然是一个有效的选择。

rebase 的优点是它避免了合并提交并创建了一些人喜欢的更线性的历史记录,并且通常不需要您保留重复的提交(即它创建提交的副本,但您通常可以在完成后丢弃原件)。历史并不能反映软件的真实编写方式,特别是它可能包含即使您以其他方式维护 "clean checkin" 策略也不会干净地构建的提交。这是历史的改写;如果您 rebase 的分支已经与其他人共享(即它已 push 在任何时候被编辑到原点),那么这可能会导致问题[1]。

如果你决定做一个变基,你可以说

git rebase master branch-2

与合并一样,您可以先 fetch, and updatemasterfrom its upstream or substituteorigin/masterformasteras needed. You can also configurepullto do arebaseinstead of amerge`,但这不被视为 "safe" 配置,只有在您对涉及的所有操作都非常满意时才应该这样做。

cherry-pick 的优点是它避免了创建合并提交,也避免了任何历史重写。但是,它会创建重复提交,这也会使历史变得有点复杂。如果在少量提交中将您想要的所有更改引入 master ,这可能是一个不错的选择。如果您最终要 merge 您的分支回到 master,它可能会增加合并冲突的机会,尽管它们不应该太难纠正。如果你最终 rebase 分支到 master,那应该不是问题(因为 rebase 有针对 cherry-pick 引入的冲突的特定保护。)如果你选择这种方法,首先确定需要复制的提交,然后

git checkout branch-2
git cherry-pick <commit>

其中 <commit> 是解析为您需要的提交的表达式 - 例如其提交 ID(哈希)或相对表达式(例如 master~2 将是第二个父级 - 即第三个最后一次提交 - 在 master 分支上)。

第二题

如果您有未提交的本地更改,您需要多加小心。 git 针对数据丢失的最有效保护不适用于工作树副本。 git 通常 尽量避免删除工作树中的数据,除非您给出的命令暗示您希望它覆盖工作树。 (不幸的是,有时并不清楚哪些命令会像那样工作。)

所以最安全的做法是,在(合并或变基或挑选)之前,存储您的更改。

git stash

然后,恢复它们

git stash pop

请注意,这可能会导致合并冲突(因为您的本地更改可能会影响与您添加到分支的提交相同的代码块)。此外,默认情况下,这会取消所有本地更改。如果您需要将暂存更改和未暂存更改分开,您可以说

git stash --index pop

但是,如果在 pop 期间发生合并冲突,则在给定 --index 选项时该命令将失败。 (到那时,您要么在没有 --index 选项的情况下继续,要么通过更多复杂的步骤来应用您的更改。如果需要,我可以进入 "more involved hoops"。)


[1] 一般来说,如果您要重写共享分支的历史记录,您需要与拥有该分支副本的每个人进行协调。如果你不这样做,那么他们处理错误的自然尝试可能会撤销重写。人们反对在分布式回购中可能不切实际;如果这是不切实际的,那么你不应该重写历史。有关详细信息,请参阅 "Recovering from upstream rebase" 下的 git rebase 文档。 https://git-scm.com/docs/git-rebase