写点什么

Git fetch、pull 傻傻分不清楚?

作者:极狐GitLab
  • 2024-09-29
    北京
  • 本文字数:3226 字

    阅读完需:约 11 分钟

Git fetch、pull 傻傻分不清楚?

Git pull 是一个 Git 命令用来同时执行 git fetch 和 git merge。本文分享了这两个命令的区别和用法。


极狐 GitLab 为 GitLab 的中文发行版,中文版本对国内用户更友好,可以一键私有化部署,也可以直接使用 SaaS,可直接申请 60 天专业版免费试用 https://dl.gitlab.cn/ig2fcdv8,导入 license 即可使用


Git 命令是非常流行的,尤其是在分布式版本控制系统中,可以对远端的仓库进行同步。开发者需要根据项目实际所需来选择合适的命令。在本文章中,我们将解释 git fetch 和 git pull 之间的区别,并且为两者不同的使用场景做一个详述。

Git fetch 和 git pull 的基本知识

Git fetch 和 git pull 都是用来从远端仓库更新信息的 Git 命令。所以,他们有什么区别呢?Git fetch 将更新从远端仓库下载到本地,但是不会对当前工作目录做任何变更。因为变更并没有被合入到本地分支,因此你可以在不打断当前工作流的情况下从远端仓库检出变更。另一方面,git pull 也能像 git fetch 一样从远端仓库拉取最新的变更,但是它却会把变更自动合入到当前分支。相比于 git fetch,git pull 直接将远端仓库的变更应用到本地工作目录中。

什么是 git fetch

git fetch 从远端仓库拉取最新的提交历史,但是不会对当前的本地工作目录产生任何影响。即使在获取(fetch)远端变更后,这些变更也不会在本地分支上有所反应。它的主要用途是:当你想要从远端仓库获取最新的状态,然后对变更被合入到本地仓库之前对变更做预览。为了将获取的变更应用到本地分支,你还需要手动执行 git merge 或者 git rebase。

什么是 git pull

git pull 命令是将 git fetch 和 git merge(或 git rebase)结合在了一起。这能够让你从远端仓库拉取(fetch)变更并且将变更自动应用到当前的本地分支上。


当用 git fetch 从远端仓库获取变更时,变更并没有应用到本地分支,而执行 git pull 命令会自动将变更从远端仓库应用到本地分支上。


Git pull 特别适合将远程变更快速反映到本地分支上,但这可能会导致冲突,因此要小心使用,特别是当多人协作时。

什么时候用 git fetch

Git fetch 是一个从远端仓库拉取最新变更信息的命令。获取的信息并不直接反映在本地分支。使用 git pull 命令则会将所有的变更都反映到本地分支上,包括不正确的或者有问题的变更,统统搞到本地分支上。


当变更同时在远端和本地分支上进行时,或者当团队内的新入职员工进行操作时,使用 git fetch 是比较安全的,可以先用 git fetch 获取变更内容,然后再执行 merge 或者 rebase 命令。

什么时候用 git pull

Git pull 是一个比 git fetch 执行更多流程的命令。Git pull 可以同时执行 git fetch 和 git merge 或 git rebase 命令。因此,当你特别希望远端变更能及时反映到本地分支上的时候,就用 git pull 吧。

实验验证

在极狐 GitLab 上创建一个 Repo,存储一个 README.md 和 1.txt 文件,其中 1.txt 文件内容如下:


cat 1.txt111122223333
复制代码


首先,保持本地和远端仓库的一致性。然后在远端仓库上将 2222 改为 2233。这时候远端仓库和本地仓库之间的代码就存在差异了,本地仓库落后远端仓库一个 commit:


Git fetch 验证

根据前面文章的描述,执行 git fetch 命令会拉取远端仓库的最新信息,但是不会将其合并到被爱分支。也就是说在本地执行 git fetch 命令后,会看到变更拉取的信息,但是查看 1.txt 的内容,依旧是 2222,验证一下结论:



# fetch 变更git fetchremote: Enumerating objects: 5, done.remote: Counting objects: 100% (5/5), done.remote: Compressing objects: 100% (2/2), done.remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)Unpacking objects: 100% (3/3), 315 bytes | 315.00 KiB/s, done.From jhma.jihulab.net:devsecops1/ai d143d7e..75eadda main -> origin/main
# 查看 1.txt 内容cat 1.txt111122223333
复制代码


可以看到 1.txt 中依旧是 2222。然后手动执行一下 git merge 或者 git rebase,再查看结果:


# 执行 git rebase 命令git rebaseSuccessfully rebased and updated refs/heads/main.
# 查看 1.txt 内容cat 1.txt111122333333
复制代码

Git pull 验证

再对远端代码做一下修改,将 1.txt 中的 3333 改为 3322。先确定本地分支上的内容,然后执行 git pull,最后再确认本地分支上的内容:


# 本地分支内容查看cat 1.txt111122333333
# git pull 命令git pullremote: Enumerating objects: 5, done.remote: Counting objects: 100% (5/5), done.remote: Compressing objects: 100% (2/2), done.remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)Unpacking objects: 100% (3/3), 321 bytes | 321.00 KiB/s, done.From jhma.jihulab.net:devsecops1/ai 75eadda..e66df87 main -> origin/mainUpdating 75eadda..e66df87Fast-forward 1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
# 再次查看本地分支内容 111122333322
复制代码


可以看到远端分支的 3333 直接变成了 3322,直接反映在了本地分支上。

进阶试验

下面来制造一个冲突,来进一步查看 git fetch 和 git pull 之间的差别。整体测试流程为:


  1. 在远端仓库新建一个 branch-1 分支;

  2. 将远端仓库中 branch-1 分支上的 3333 改为 4444;

  3. 将本地 branch-1 分支上的 3333 改为 5555;

  4. 分别执行 git fetch 和 git pull 命令查看结果


首先看执行 git fetch 的结果:


# 执行 git fetch 命令git fetch origin branch-1From jhma.jihulab.net:devsecops1/ai * branch            branch-1   -> FETCH_HEAD
# 查看 branch-1 分支上的内容cat 1.txt111122225555
复制代码


可以看到 1.txt 文件中的 3333 变成了 5555。这个符合预期,因为 git fetch 会拉取变更,但是不会合并到本地分支,接着执行 git merge 或者 git rebase 命令:


git mergeAuto-merging 1.txtCONFLICT (content): Merge conflict in 1.txtAutomatic merge failed; fix conflicts and then commit the result.
复制代码


提示冲突,然后打开 1.txt 文件查看:


11112222<<<<<<< HEAD5555=======4444>>>>>>> refs/remotes/origin/branch-1
复制代码


可以看到冲突的内容,此时解决冲突的时候,只要确保保留哪些内容即可,比如保留 4444 那就把 5555 删除,然后重新提交代即可:


# 提交代码git add . && git commit -m "fix confilict"[branch-1 77f28b1] fix confilict
# 推动代码git push origin branch-1Enumerating objects: 8, done.Counting objects: 100% (8/8), done.Delta compression using up to 2 threadsCompressing objects: 100% (3/3), done.Writing objects: 100% (4/4), 511 bytes | 511.00 KiB/s, done.Total 4 (delta 0), reused 0 (delta 0), pack-reused 0remote:remote: To create a merge request for branch-1, visit:remote: http://jhma.jihulab.net/devsecops1/ai/-/merge_requests/new?merge_request%5Bsource_branch%5D=branch-1remote:To jhma.jihulab.net:devsecops1/ai.git 55ce9b9..77f28b1 branch-1 -> branch-1
复制代码


前面是 git fetch 在面对冲突时候的表现。还是最开始的条件,如果直接执行 git pull 会有什么不同吗?


# 远端 branch-1 分支内容111122225555
# 本地 branch-1 分支内容111122224444
# git pull 命令Auto-merging 1.txtCONFLICT (content): Merge conflict in 1.txtAutomatic merge failed; fix conflicts and then commit the result.
# 查看冲突内容11112222<<<<<<< HEAD5555=======4444>>>>>>> a91c399bb2772f5a121830638d138264df27c9ee
复制代码


剩下的冲突解决和上面的就一样了。

总结

Git fetch 和 Git pull 虽然都是从远端仓库将变更拉取到本地的命令,但是两者在作用上有所不同,简言之:Git fetch 拉取变更但是不将变更应用到本地分支;Git pull 拉取变更同时将变更应用到本地分支,可以理解为 Git pull = Git fetch + Git merge(or rebase)

用户头像

极狐GitLab

关注

开源开放,人人贡献 2021-05-19 加入

开放式一体化DevOps平台,助力行业高速协同增长!

评论

发布
暂无评论
Git fetch、pull 傻傻分不清楚?_git_极狐GitLab_InfoQ写作社区