彻底理解git 本地分支与远程分支,以及git pull与git fetch的区别, 以及git status输出的“Your branch is behind xxx”

git 本地分支:

当clone一个远程repo之后,默认会新建一个master或main的本地分支。

比如:

$ git branch -a
* main
  remotes/origin/HEAD -> origin/main
  remotes/origin/develop
  remotes/origin/main

可以看到本地默认只建了一个main分支,剩下的都是远程分支。

可以在远程分支基础上checkout出一个本地分支来,比如执行命令:

$ git checkout develop
Branch 'develop' set up to track remote branch 'develop' from 'origin'.
Switched to a new branch 'develop'

 这是一个本地分支develop被创建出来。

Git远程分支:

就是上边输出的名字以remotes/origin/开始的分支。虽然叫远程分支,但是这些分支所对应的commits也是在我们本地的,严格来说应该叫本地的远程分支(有些别扭)。下文说的远程分支都是指这种分支,而不是指远程仓库上的分支。

同时我们也可以将远程分支checkout出来,只不过这个远程分支是只读的,也即我们处于'detached HEAD'状态。

$ git checkout remotes/origin/develop
Note: switching to 'remotes/origin/develop'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 098c616 Create file-in-develop

我们想在本地修改,提交然后同步到远程repo,必须在本地分支上工作,而不能在远程分支操作。

我们在执行git fetch操作的时候,会将远程仓库的commits,files,ref等信息下载到本地,并保存在以remotes/origin/ 开始的分支中(这样说并不准确,严格来说是让remotes/origin/ 开始的分支指向这些新的commits),底层的原理如下图:

 我们所有的commits都是类似于一个链表似的,所有分支的commits都互相连接在一起,不管是本地的分支(上图中main指向的)还是远程分支(上图中名字以Orgin/开始的分支),他们都指向这个commits链条的某个点(没错,分支名就是指针,指向某个提交)。我们执行git fetch命令时,会将远程的commits下载下来,让名字以remotes/origin开始的分支去指向他们。但是这些remote的commits,我们是没办法直接在上边工作的(修改操作),我们可以先将这些包含新的commits的远程分支checkout来,然后在此基础上新建一个分支,然后再做修改。

或者我们可以直接将这些远程分支merge到我们的本地分支,比如:

$ git fetch origin develop
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (2/2), 609 bytes | 304.00 KiB/s, done.
From https://github.com/YiyiSmile/test06087
 * branch            develop    -> FETCH_HEAD
   90b6713..311a291  develop    -> origin/develop
$ 
$ 
$ git status
On branch develop
Your branch is behind 'origin/develop' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean
$ ls
README.md	a		file-in-develop	file2		file3		hello		world
$ git merge origin/develop
Updating 90b6713..311a291
Fast-forward
 file4 | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 file4
$ ls
README.md	file-in-develop	file3		hello
a		file2		file4		world

 我们先用git fetch将远程repo上的develop分支的新的提交(file4)下载到本地的origin/develop分支上,这时本地的develop分支完全没有受影响,工作区,stage区和提交区都没有变化。然后执行merge命令,将origin/develop分支 merge到本地分支develop。

除了用merge命令,还可以简单用git pull来完成将快进(fast forward),将origin/develop里有的commits 合并到我们本地的develop分支。

git pull操作:

 git pull与git fetch的区别具体可以参考文档:

Git Fetch | Atlassian Git Tutorial

git fetch是将远程repo数据下载到本地,但对本地仓库完全没有影响。而git pull会将远程仓库数据下载到本地,并自动完成合并,更新工作区和stage区(索引区)。 

git status输出的理解:

比如我们在远程仓库develop闻分支新建一个文件file5,然后执行命令git status,发现并没有提示消息:Your branch is behind 'origin/develop' by 1 commit

 

$ git status
On branch develop
Your branch is up to date with 'origin/develop'.

nothing to commit, working tree clean
$ ls
README.md	file-in-develop	file3		hello
a		file2		file4		world

 这时,我们可以通过两种方式让该消息出现:

方式一:可以在别的分支下,比如main分支下,执行git pull,后边不带任何参数。这时除了远程仓库的main分支数据会被下载下来,其他所有分支的数据会被拉下来,但是只有当前所在的本地分支main会自动与远程同步,完成merge、工作区、stage区的同步。而其他分支,比如这里的develop分支,他们并不会同步。但是对应的远程分支(orgin/develop)却完成了同步。

方式二:执行git fetch命令。

当orgin/develop指向了从远程下载下来的新的提交,而本地的develop还是指向老的提交,这时运行git status命令时,就会看到“Your branch is behind 'origin/develop' by 1 commit”消息。

$ git fetch
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 646 bytes | 323.00 KiB/s, done.
From https://github.com/YiyiSmile/test06087
   311a291..634ba9e  develop    -> origin/develop
$ git status
On branch develop
Your branch is behind 'origin/develop' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)

nothing to commit, working tree clean

 总结:

 也就是说并不是只要远程仓库有更新了,git status就会报告你的本地分支落后于远程分支。而是只有当远程仓库的数据同步到本地的名字以origin/开始的分支之后,git status才会比较本地与远程分支的差异。这个比较过程都是在本地完成的,不存在网络通信过程。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值