从远程Git仓库拉取更改

6

我是git的新手。我所做的是fork一些我感兴趣的存储库,然后将它们克隆到我的电脑上进行操作。

一些原始项目可能会在我操作本地副本之前显着更新,或者我可能会进行一些微不足道的更改。

据我所知,我可以“rebase”我的克隆以“pull”原始项目中的更改。

那对我的更改有什么影响?例如,假设有一个名为DoSomething.cpp的文件来自原始项目。我修改了它,可能修复了一个小bug或添加了一个功能。现在! 1年后,原始项目已经经历了许多修订,变得更好了。我想将这些更改“pull”到我的克隆中,但仍然保留我的更改!(所以这有点像推送的反向)

这很容易做到吗?如果可以,基本思路是什么?

我希望我的克隆中的任何更改(我已更改的内容)不会被覆盖,但我实际上可以将我的更改与原始代码(在我的fork上)合并,并有能力检查和接受更改。 (例如,如果在原始代码中更改了DoSomething.cpp,则需要比较更改以确保它们兼容)。

我猜这不难,因为我是fork的所有者,我可以重新设置或硬重置它,然后将我的本地更改推送到我的fork?(不确定它是否有效,因为存在版本问题的巨大潜力)


git pull --rebase 会启发式地尝试合并更改;如果无法合并,它将告诉您合并失败,并要求您执行合并操作。 - Fred Foo
@larsmans:所以,我想我需要一些工具来重新定位,警告我并显示问题,可能让我修复,然后再尝试重新定位,直到没有错误为止?也就是说,重新定位是一个全有或全无的过程吗? - jsmdnq
1
这正是Git已经做的事情。为什么不在一个空白的仓库上尝试一下呢? - Fred Foo
4个回答

1
  1. 找出你所在的分支,使用 git status 命令,它会在第一或第二行显示分支名称。

  2. 为了测试,建议先将更改分支到一个单独的分支中:

    git checkout -b my-patches
    
  3. 现在确保所有更改都已提交。为此,再次调用 git status 命令。理想情况下,它应该显示“工作目录干净”,但如果不是这种情况,请使用 git add 将更改添加到索引中,并使用 git commit 最终提交它们。如果您想将更改拆分成几个不同的补丁集(当发生冲突时可能很方便),建议您阅读如何使用 git commit -p。重复此过程,直到所有更改都不再列在 git status 中。列表中将列出一些您没有触及的文件,可能是构建结果。如果没有任何您感兴趣的更改需要保留在其中,那么就没问题了。

    如果有任何 makefile 或类似的东西支持清理目录(例如 make clean),请现在运行它们。

  4. 然后使用以下命令切换回原始分支(将 master 替换为您在步骤 1 中找到的任何分支名称):

    git checkout master
    

    如果您想确保一切正常,请运行:

    git diff my-patches
    

    它应该列出您在 fork 中更改的行。如果没有,那么就出了问题。

  5. 现在是可怕的部分。您将放弃对此分支所做的任何更改。请注意,如果您按照第 3 步中描述的将所有更改提交到单独的分支中,则它们将很好。如果您不确定,可以通过复制整个存储库文件夹来进行备份。然后运行(同样,将 master 替换为之前的内容):

    git fetch
    git reset --hard origin/master
    
  6. 理想情况下,您的分支现在应该具有与 origin/master 分支完全相同的状态。确保一切看起来都没问题。然后使用以下命令合并回您的更改:

    git merge my-patches
    

    Git 将尽其所能使其尽可能无忧无虑,但可能会出现冲突。 Git 将在相应的文件中使用 >>>>`<<<< 标记标记这些冲突。为了解决冲突,建议您进行一些互联网研究或阅读 开放 Git 书籍中有关基本合并冲突的部分。确保在合并后提交合并。

  7. 困难的部分已经过去了。现在可以删除临时分支:

    git branch -d my-patches
    

    我使用临时分支的原因是为了能够轻松地将存储库的状态还原到合并尝试之前的状态。当然,也可以在单独的分支中检出


1
首先,你应该知道无论你是"合并(merge)"还是"变基(rebase)",你不会丢失你的更改,git 会让你有机会提交你的更改并解决冲突(如果有),然后将修改推回你正在拉取的远程仓库。
当你执行git pull时,你告诉git这样做:(默认使用"合并")

从远程拉取文件的最新副本,与我本地的更改进行合并。如果有冲突无法自动解决,则通知我以便手动解决;这很简单。

当你执行git pull --rebase时,你告诉git这样做:

暂时移除*我的本地副本中的更改(我的修改文件),从远程拉取最新的副本,将我的更改合并在其顶部。如果有冲突无法自动解决,则通知我以便手动解决。(技术上没有任何东西被移除;这只是为了使这个原本模糊的逻辑更加清晰。

两种情况之间的差异微妙,在第二种情况下,您的更改似乎就像您刚刚在最近从远程拉取的副本的顶部进行了这些更改一样...但正如您所看到的,在这两种情况下,您的更改肯定被保留(否则 Git 有何用处!)。

您应该合并还是变基?这是一个长时间的讨论,有些情况下其中一种方法比另一种更好,并且有最佳实践;此页面中已经提到了一些有用的评论,如果需要更多信息,可以在线搜索,只需输入“git merge vs rebase”,您将看到很多相关页面:)

希望这可以帮助到您。


1

没错,变基是一种保持代码更新的方法,而且非常常用。

根据我的经验,变基在管理git历史方面更有用。它使你的历史线性化,看起来工作是按顺序而不是并行进行的。另一方面,常规合并将涉及许多分叉/汇合提交。您可以使用git log --graph以可视化方式查看这种差异。

简而言之,rebase将您的提交转换为补丁,然后将其应用于您正在变基的分支。如果存在冲突,则git会停止并要求您解决冲突,然后您可以让它继续。因此,您仍然在合并和解决冲突,但只是以使历史线性化的方式进行。


0

你在 fork 的仓库中添加了上游远程仓库吗?这是保持你的 fork 与其主分支同步的最简单方法。这是第三步这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接