git push/git pull/git fetch/git merge图解

不同于svn中心仓库/版本库的理念,git首先是本地仓库,然后是远程仓库(github、gitee等)。协作者通过各自本地仓库与共同的远程中央仓库(例如github)进行同步来协同工作(注:这种类似svn的方式称为集中式工作流,有多种其他工作流,例如 GitHub flow https://zhuanlan.zhihu.com/p/81396787 )。
区别:

总体流程

准备工作

方式1:先建立远程库(master分支),然后git clone url克隆远程库。
方式2:建立本地库git init,然后与远程库建立连接,git remote add [shortname] [master分支url]

git fetch

git fetch 从远程存储库下载commits, files, refs到本地仓库,但是不会合并到本地仓库。
可以用来查看远程仓库的进展情况而不影响本地工作。获取的内容位于/.git/refs/remotes/.git/objects 文件夹下
远程分支的提交在下图中显示为正方形

范例,远程仓库origin/master节点与本地仓库master节点未合并

git pull

git pullgit fetchgit merge的结合。
从远程获取更新并合并到本地仓库,pull合并采用Recursive策略(Git在对两个分支进行合并时所采用的默认策略,它只适用于两个分支之间的合并)

git push

用于将本地存储库发布到中央/远程存储库。
push合并采用fast-forwardable方式,因此push之前,需要先从远程仓库获取最新的更新(先git pull),
push之后本地库的remote/origin/master的head指针和master的head指针将指向同一个commit ID,且远程库也同样如此。

范例,push前,remote/origin/master的head指针和本地master的head指针将指向不同的commit ID,push后指向相同的commit ID


附录 - 分支合并策略

本地仓库的两个分支master和develop,其合并策略与同一分支的本地分支(maste)和远程分支(origin/maste)合并是一样的道理。
下面是本地仓库,把 develop 分支合并到 main 分支上。

git checkout master
git merge develop 

根据分支从最近分叉后各自的提交情况,分两种:

情况一:fast-forward merge

当develop和master分支自m3分叉后,master分支没有新的commit,但是develop分支有新的commit,那么执行git merge 将会自动采用此策略,此策略不生成新的commit id,只改变head指向

如果想强制产生新的合并commit, 使用 git merge --no-ff,会产生新的commit,并将head指向此commit.
当使用--no-ff参数进行合并时,合并方式其实就变成了Three-Way Merge了

情况二:Three-Way Merge

例如 develop 分支和 master 分支,自m3分叉后都各自有新的commit,那么执行git merge时会自动采用此策略,此策略会产生新的commit,并将head指向此commit

特殊的合并 git rebase

简单地说,Rebase就是把一个分支上的所有提交,在另一个分支上按照同样的顺序重新“回放”(replay)一遍。
示例,feature分支和develop分支自C3分叉后各自都有新的提交,为了保持线性历史,避免Three-Way Merge,可以将feature分支上新提交合并到develop最新的提交C7之后:
执行:

# 在feature分支上执行rebase ,意思是develop的最新提交 C7 作为feature分支的新的起点。
git checkout feature
git rebase develop 

# 回到develop 分支
git checkout develop 
git merge feature # 因为不存在分叉,所以Git自动采用Fast-Forward方式进行合并

结果就是feature合并进了develop,且呈现为线性历史。没有Three-Way的merge节点。

参考:https://morningspace.github.io/tech/git-merge-stories-6/

posted @ 2022-11-18 17:51  悠哉大斌  阅读(1142)  评论(1)    收藏  举报