git从源分支拉入时出现奇怪问题
我的一位同事将一家分行(BranchA)推到回购协议上 然后,我从BranchA创建了这个分支(testBranch)的副本 一切都很好 这位同事接着又向布兰卡提出了两项承诺 然后我有git pull(从回购中获取最新的变更) 但是,我没有看到提交的两个文件 回购 布兰卡 本地git从源分支拉入时出现奇怪问题,git,Git,我的一位同事将一家分行(BranchA)推到回购协议上 然后,我从BranchA创建了这个分支(testBranch)的副本 一切都很好 这位同事接着又向布兰卡提出了两项承诺 然后我有git pull(从回购中获取最新的变更) 但是,我没有看到提交的两个文件 回购 布兰卡 本地 git checkout master git pull git checkout testBranch origin/BranchA git merge master 我不确定为什么看不到最新的提交(文件) 解决方法
git checkout master
git pull
git checkout testBranch origin/BranchA
git merge master
我不确定为什么看不到最新的提交(文件)
解决方法:
我觉得我好像错过了一步?感觉很奇怪,每次我需要从特定的源/分支获取最新的更改时,我都必须删除该分支您已经从
BranchA
创建了一个新分支testBranch
。而您的同事将更改推到了BranchA
。但您仍然在testBranch
。因此,您的远程分支没有要拉取的更改,这就解释了为什么在testBranch
中看不到BranchA
中的提交
...--o--o--* <-- BranchA
..--o--o--*您已经从BranchA
创建了一个新分支testBranch
。而您的同事将更改推到了BranchA
。但您仍然在testBranch
。因此,您的远程分支没有要拉取的更改,这就解释了为什么在testBranch
中看不到BranchA
中的提交
...--o--o--* <-- BranchA
…--o--o--*您将太多的魔力归于分支。:-)
Git的工作方式非常简单。分支名称只是一个Git提交哈希ID的名称(我还建议您忘记,Git pull
甚至存在,但我们很快就会看到它是什么,以及如何使用它)
关于提交、哈希ID、分支名称和提交链
让我们稍微讨论一下这些提交哈希ID。散列ID是一大串难看的字母和数字,例如0d0ac3826a3bbb9247e39e12623bbcfdd722f24c
。这唯一地标识了一些Git对象,通常是一个提交,当我们使用分支名称时,它肯定是一个提交。每个提交都记录其父提交或前置提交的哈希ID。这允许Git将提交串成一个向后看的链
这意味着我们可以绘制这些提交链。如果我们让一个大写字母代表一个丑陋的大哈希ID,我们会得到如下结果:
... <-F <-G <-H <--master
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch (HEAD), BranchA
\
K--L <-- origin/BranchA
现在Git只需将I
的散列ID写入master
名称中,这样master
现在就指向I
:
...--F--G--H--I <-- master
(稍后我们将进一步讨论远程跟踪名称。它们有点像分支名称,但有点扭曲。)
当您创建一个新的分支名称时,Git所要做的就是使新名称指向某个现有的提交。例如,现在让我们使用git checkout BranchA创建自己的BranchA
:1
如果您现在创建一个新的提交,您的Git需要知道更新哪个分支名称。因此,您的Git有一个特殊的名称,HEAD
,用所有大写字母写成。2 Git将此名称附加到您的一个分支名称上:
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch (HEAD), BranchA, origin/BranchA
您的Git将在源代码下列出的URL处调用他们的Git,并询问他们的Git关于分支的信息。他们会说:哦,当然,给你:我的master
是,我的BranchA
是。(要查看这一点,请运行git ls remote origin
,这与git fetch origin
类似,只是在获取远程名称和哈希列表后,它只打印出来。)
有了这个列表,您的Git会继续要求他们的Git提交您没有的任何新提交。因此,如果他们已经更新了他们的BranchA
,您将得到他们的新提交。然后,不管发生了什么,Git现在设置所有以origin/
开头的远程跟踪名称。也就是说,假设他们有两个新的提交。您自己的存储库现在如下所示:
... <-F <-G <-H <--master
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch (HEAD), BranchA
\
K--L <-- origin/BranchA
在git合并之前
,我们的存储库中有以下内容:
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch, BranchA (HEAD)
\
K--L <-- origin/BranchA
现在,commitL
作为当前提交,commitL
将填充索引和工作树。是时候谈谈这两个人了
索引和工作树
我们已经提到,存储在提交中的文件是完全、完全、100%冻结/只读的。它们以一种特殊的、压缩的、仅限Git的格式存储。这让Git可以节省大量空间,并重用未更改的文件:如果新提交的文件与上一次提交的文件基本相同,则无需保存所有文件。旧提交的副本已冻结,因此新提交只能共享它们。(这个过程的细节在这里并不重要,但Git使用哈希ID(Git称之为blob对象)来实现这个技巧。)
这对Git来说很好,但我们不能使用冻结的压缩Git文件来做任何其他事情。因此Git必须将冻结的文件解冻并反压缩为正常的日常形式,以便我们和计算机上的其他程序能够使用它们
解冻后的文件进入工作树,这被称为工作树,因为我们在那里处理它们。在这里,我们可以用我们的文件做任何我们想做的事情。因此,对于每个文件,当前提交中有一个冻结副本,工作树中有一个解冻副本。(在其他提交中也可能存在冻结副本,但当前提交中的副本最有趣,因为我们可以并且经常将其与工作树中的副本进行比较。)
索引,也称为暂存区,有时也称为缓存,是Git特有的东西。其他版本控制系统也冻结了提交
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch (HEAD), BranchA, origin/BranchA
git fetch origin
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch (HEAD), BranchA
\
K--L <-- origin/BranchA
git checkout BranchA
git merge origin/BranchA
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch, BranchA (HEAD)
\
K--L <-- origin/BranchA
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch
\
K--L <-- BranchA (HEAD), origin/BranchA
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch
\
K--L <-- BranchA (HEAD), origin/BranchA
git checkout testBranch
git merge <anything that identifies commit L>
...--F--G--H <-- master, origin/master
\
I--J
\
K--L <-- testBranch, BranchA, origin/BranchA
...--F--G--H <-- master, origin/master
\
I--J <-- testBranch (HEAD)
\
K--L <-- origin/BranchA
$ git clone <url>
$ cd <repository>
$ git checkout -b testBranch origin/BranchA
... wait until colleague updates origin/BranchA ...
$ git fetch # defaults to using origin
$ git merge origin/BranchA
git pull origin master
git fetch origin master
git merge -m "merge branch 'master' of $url" origin/master