ios - 为什么git pull不更新本地更改的文件?

标签 ios git macos

据我了解,“ git pull”会进行获取和合并。对于iOS项目,我使用发布设置(证书,配置文件等)配置了设置。但是,当在master分支上时,当我执行git pullgit log时,我看到git提交与远程主分支的最新提交保持最新,但git diff仍显示我的pbxproj文件是不同(即与我在本地配置的提供概要文件字符串等)不同。

明确地说,这对我来说是理想的,因为我只希望代码更改,而不必在每次发布分支之前(在即将发布到生产环境之前)更新分支和设置概要文件。但我也想了解git合并的方式。我期望git将合并我在本地更改的文件和/或表明冲突。但是没有发生这样的事情。

注意:我知道一个“强制更新”,它使我的本地主服务器完全类似于远程主机,但想了解此操作与常规合并之间的区别。

最佳答案

据我了解,“ git pull”会进行获取和合并。


没错更准确地说,git pull实际上运行git fetch,然后运行git merge。或者更确切地说,它曾经是过去的字面意思。在过去一年左右的时间里,对Git进行了修改,以通过在内部进行获取和合并步骤来加快git pull的速度,而不是在可能的情况下运行单独的命令-并且您还可以告诉它执行git rebase而不是git merge ,还有其他一些极端情况。但实际上,pull =提取+合并。

棘手的部分是这两个步骤分别意味着什么。提取和合并都很复杂,也可能很复杂。



提取步骤更简单:您的Git调用其他Git。您的Git和他们的Git进行了一段简短的交谈,其中他们的Git告诉您的Git他们有任何新提交,而您没有。您的Git将这些新的提交加载到您的存储库中,以便您现在拥有这些提交;然后,您的Git设置您的远程跟踪名称(如origin/master之类的名称)以记住其Git的master等。 (当git pull运行git fetch时,可能会限制您的Git的获取。在非常旧的版本中,这甚至也会阻止您的Git更新您的origin/master等。现代Git消除了最后一个无用的特性。)

只要您自己不使它复杂化(通过添加refspecs或各种获取标志),就足够了。合并部分仍然很棘手。完成提取后,git pull现在运行git merge,这会使事情变得有些复杂。

合并

合并的目标很简单:Git首先假设您一直在工作并进行提交,而其他人也一直在工作并进行提交。如果我们将这些提交以较早的提交向左绘制,然后将较后的提交向右绘制,给它们提供一个简单的单字母名称,而不是其实际的难以理解的吉蒂哈希ID,我们将得到如下所示:

          C--D--E   <-- branch (HEAD)
         /
...--A--B
         \
          F--G--H   <-- origin/branch


E是分支上的最新提交。其父是commit D; D的父母是C;等等。提交H是他们的最新提交,您刚刚通过git fetch引入了该提交。 H的父级是G,其父级是F,其父级是B。我们可以看到,从提交B的共同点(合并基础)开始,这两条开发线并行发生。

在这种情况下,git merge的作用实际上是运行两个git diff命令。第一个找出您所做的更改:

git diff --find-renames <hash-of-B> <hash-of-E>


第二个差异找出了它们的变化:

git diff --find-renames <hash-of-B> <hash-of-H>


Git可以将这两组不同的更改组合在一起,只要它们彼此不冲突即可。或者更确切地说,只要Git不认为它们发生冲突-Git不知道,它就对git diff的逐行差异做出了很多假设。成功(也许)组合更改后,Git将组合的更改应用于合并基础中的快照以生成新快照,并与两个父级进行合并提交:

          C--D--E
         /       \
...--A--B         I   <-- branch (HEAD)
         \       /
          F--G--H   <-- origin/branch


进行新的合并提交会使分支名称本身branch指向新的提交,就像进行新的普通提交一样。

这是一个真正的合并:Git必须合并自合并基础以来的更改,这意味着它必须首先找到合并基础提交,然后进行两个比较。这是合并的动词部分,用于合并(两组更改)。在完成了要合并的动词部分后,Git进行了合并提交,将其合并为形容词,或者更不正式地进行了合并(使用merge作为名词)。

并非所有合并都是真实的合并

假设您运行git fetch(也许通过git pull)并且什么都没有改变,那么您将:

...--D--E   <-- branch (HEAD), origin/branch


也就是说,您在这里有两个不同的名称。您的分支名称为branch,指向您的哈希ID为E的提交(确实是一些难看的Git哈希)。您还有一个远程跟踪名称origin/branch,记住他们的Git分支名为branch,指向您的哈希ID为E的提交,因为两个Git中都存在相同的提交。

然后,不做任何工作也不做任何提交,您稍后再运行git fetch,只是这一次他们做了一些工作并进行了一些提交:

...--D--E   <-- branch (HEAD)
         \
          F--G   <-- origin/branch


如果现在您要求Git将您的工作(或缺少工作)与他们的工作合并,则Git会照常找到合并基础,但是会发现合并基础本身就是E提交。显然,将提交E与自身进行比较不会发现任何变化。无论如何,Git可以继续构建新的合并提交,将无更改与某些更改结合起来以得到:

...--D--E------H   <-- branch (HEAD)
         \    /
          F--G   <-- origin/branch


H中的快照与G中的快照完全匹配。但是git merge的默认设置是不打扰。合并将其检测为快进操作,而不是执行合并动词,也不进行形容词合并提交。 Git只会将分支名称H向前移动,而不是进行新的提交branch

...--D--E
         \
          F--G   <-- branch (HEAD), origin/branch


并检出提交G,以便G的快照填充索引和工作树。

Git将此称为快速合并,但是没有合并!快进只是对分支名称的操作。最终没有任何痕迹发生,这就是为什么Git允许您禁止快速前进的非合并“合并”的原因。但是,对于与远程跟踪名称相对应的本地分支,无论如何实际上实际上都是这种情况,这就是Git的默认设置。

关于ios - 为什么git pull不更新本地更改的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51330682/

相关文章:

objective-c - 将 SBJson framwork + ShareKit/ShareKit 添加到同一个 XCode 项目

objective-c - animateWithDuration 如何知道要为什么设置动画?

ios - Swift 中的方法调配

git - Git merge 的顺序重要吗?

xcode - 用于同一产品不断发展的变体的最佳 git 和 Xcode 结构

objective-c - 如何打印字体的字符集?

ios - xCode - 如何判断某些东西是否会被弃用?

git:重命名后如何交互添加(-p)

swift - macOS Swift 3 - 处理通知警报操作按钮

python - 为 macosx 不兼容的库安装 opencv