Git: Git获取与安全更新详解

获取(Fetch)是从远程仓库下载更新但不自动合并的操作。相比pull,fetch更安全可控,可以先查看更新内容再决定是否合并。理解fetch的使用对团队协作非常重要。

1. 获取基础概念

(1) 什么是获取

获取是从远程仓库下载更新的操作,但不会修改当前分支:

100%
graph TB
    A[远程仓库<br/>Remote] -->|git fetch| B[远程分支副本<br/>origin/main]
    B --> C{查看更新}
    C -->|满意| D[git merge]
    C -->|不满意| E[保持原状]
    D --> F[当前分支<br/>main]
    
    style A fill:#d4edda
    style B fill:#fff3cd
    style F fill:#c3e6cb

(2) fetch vs pull

特性 fetch pull
下载更新
自动合并
修改当前分支
安全性
可控性

(3) 获取的作用


2. 基本获取操作

(1) 获取所有更新

▶ 示例:获取更新

BASH
# 获取所有远程仓库的更新
git fetch

# 输出:
# remote: Enumerating objects: 8, done.
# remote: Counting objects: 100% (8/8), done.
# remote: Compressing objects: 100% (5/5), done.
# remote: Total 5 (delta 3), reused 0 (delta 0), pack-reused 0
# Unpacking objects: 100% (5/5), 1.23 KiB | 1.23 MiB/s, done.
# From https://github.com/user/repo
#    a1b2c3d..d4e5f6g  main        -> origin/main
#  * [new branch]      feature     -> origin/feature
#  * [new tag]         v1.0.0      -> v1.0.0

(2) 获取特定远程

▶ 示例:获取特定远程

BASH
# 获取origin的更新
git fetch origin

# 获取upstream的更新
git fetch upstream

# 获取所有远程仓库
git fetch --all

# 输出:
# Fetching origin
# Fetching upstream
# Fetching backup

(3) 获取特定分支

▶ 示例:获取特定分支

BASH
# 获取特定分支
git fetch origin main

# 获取多个分支
git fetch origin main develop

# 获取远程分支到本地不同名称
git fetch origin main:local-main

# 获取并创建本地分支
git fetch origin feature:feature

3. 查看获取的更新

(1) 查看远程分支

▶ 示例:查看远程分支

BASH
# 获取更新
git fetch origin

# 查看远程分支
git branch -r

# 输出:
#   origin/HEAD -> origin/main
#   origin/main
#   origin/develop
#   origin/feature

# 查看所有分支
git branch -a

# 输出:
# * main
#   develop
#   remotes/origin/HEAD -> origin/main
#   remotes/origin/main
#   remotes/origin/develop
#   remotes/origin/feature

(2) 查看远程更新内容

▶ 示例:查看更新详情

BASH
# 查看远程分支的最新提交
git log origin/main

# 输出:
# commit d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2
# Author: 张三 <zhangsan@example.com>
# Date:   Mon Jan 1 10:00:00 2026 +0800
#
#     feat: 添加新功能

# 查看远程的新提交(本地没有的)
git log main..origin/main

# 输出:
# d4e5f6g (origin/main) feat: 添加新功能
# h7i8j9k fix: 修复Bug

# 查看本地有但远程没有的提交
git log origin/main..main

# 查看双向差异
git log main...origin/main

(3) 比较本地和远程

▶ 示例:比较差异

BASH
# 比较本地和远程的差异
git diff main origin/main

# 查看差异统计
git diff --stat main origin/main

# 输出:
#  src/auth.js  | 10 ++++++++++
#  src/user.js  |  5 ++---
#  2 files changed, 12 insertions(+), 3 deletions(-)

# 查看修改的文件列表
git diff --name-only main origin/main

# 输出:
# src/auth.js
# src/user.js

# 查看详细的文件状态
git diff --name-status main origin/main

# 输出:
# M  src/auth.js
# M  src/user.js

4. 合并获取的更新

(1) 合并远程更新

▶ 示例:合并更新

BASH
# 获取更新
git fetch origin

# 查看更新
git log main..origin/main

# 合并远程更新
git merge origin/main

# 输出:
# Updating a1b2c3d..d4e5f6g
# Fast-forward
#  src/auth.js | 10 ++++++++++
#  1 file changed, 10 insertions(+)

(2) 使用rebase合并

▶ 示例:rebase更新

BASH
# 获取更新
git fetch origin

# 使用rebase合并
git rebase origin/main

# 输出:
# First, rewinding head to replay your work on top of it...
# Fast-forwarded main to d4e5f6g.

# 如果有冲突
# CONFLICT (content): Merge conflict in file.js
# 解决冲突后
git add file.js
git rebase --continue

(3) 选择性合并

▶ 示例:cherry-pick特定提交

BASH
# 获取更新
git fetch origin

# 查看远程的新提交
git log main..origin/main --oneline

# 输出:
# d4e5f6g feat: 添加功能C
# h7i8j9k fix: 修复Bug
# k9l0m1n feat: 添加功能B

# 只合并某个提交
git cherry-pick h7i8j9k

# 或者合并多个提交
git cherry-pick k9l0m1n d4e5f6g

5. 获取标签

(1) 获取远程标签

▶ 示例:获取标签

BASH
# 获取更新(包括标签)
git fetch origin

# 输出:
#  * [new tag]         v1.0.0      -> v1.0.0
#  * [new tag]         v1.1.0      -> v1.1.0

# 查看所有标签
git tag

# 输出:
# v1.0.0
# v1.1.0

# 查看标签详情
git show v1.0.0

(2) 获取特定标签

▶ 示例:获取特定标签

BASH
# 获取特定标签
git fetch origin refs/tags/v1.0.0:refs/tags/v1.0.0

# 获取所有标签
git fetch --tags

# 删除本地标签(远程已删除)
git fetch --prune-tags

# 或者
git fetch -p --prune-tags

6. 获取选项详解

(1) 常用获取选项

选项 说明 使用场景
--all 获取所有远程 更新所有远程
-p 清理过期引用 远程分支已删除
--tags 获取所有标签 同步标签
--prune-tags 清理过期标签 标签已删除
--dry-run 模拟获取 预览获取内容
--verbose 详细输出 调试获取

▶ 示例:使用获取选项

BASH
# 清理过期的远程分支引用
git fetch -p

# 输出:
# From https://github.com/user/repo
#  x [deleted]         (none)     -> origin/old-feature

# 清理过期的标签
git fetch --prune-tags

# 模拟获取
git fetch --dry-run

# 详细输出
git fetch --verbose

# 获取深度(浅克隆)
git fetch --depth=1

# 获取单分支
git fetch --single-branch

(2) 清理过期引用

▶ 示例:清理远程引用

BASH
# 查看需要清理的分支
git remote prune origin --dry-run

# 输出:
# * origin/deleted-branch would be pruned

# 执行清理
git remote prune origin

# 或者使用fetch -p
git fetch -p

# 输出:
# From https://github.com/user/repo
#  x [deleted]         (none)     -> origin/deleted-branch

7. fetch工作流

(1) 安全更新工作流

100%
sequenceDiagram
    participant 开发者
    participant 本地仓库
    participant 远程分支
    participant 远程仓库
    
    开发者->>远程仓库: git fetch origin
    远程仓库->>远程分支: 更新origin/main
    开发者->>远程分支: git log main..origin/main
    开发者->>远程分支: git diff main origin/main
    开发者->>本地仓库: git merge origin/main

(2) 实际应用场景

▶ 示例:fetch工作流

BASH
# 场景1:开始工作前检查更新
git fetch origin
git log main..origin/main --oneline

# 输出:
# d4e5f6g feat: 新功能
# h7i8j9k fix: Bug修复

# 查看具体修改
git diff main origin/main

# 决定是否合并
git merge origin/main

# 场景2:有未提交的工作,先获取再决定
git fetch origin
git status

# 输出:
# On branch main
# Your branch is behind 'origin/main' by 2 commits.

# 查看更新内容
git log HEAD..origin/main

# 暂存当前工作
git stash

# 合并更新
git merge origin/main

# 恢复工作
git stash pop

# 场景3:Fork工作流
git fetch upstream
git log main..upstream/main
git merge upstream/main
git push origin main

(3) 定期同步脚本

▶ 示例:自动同步脚本

BASH
#!/bin/bash
# sync.sh - 定期同步远程更新

# 获取所有远程更新
git fetch --all

# 检查每个分支的状态
for branch in $(git branch --format='%(refname:short)'); do
    upstream=$(git rev-parse --abbrev-ref $branch@{upstream} 2>/dev/null)
    if [ -n "$upstream" ]; then
        behind=$(git rev-list --count $branch..$upstream 2>/dev/null)
        ahead=$(git rev-list --count $upstream..$branch 2>/dev/null)
        if [ "$behind" -gt 0 ] || [ "$ahead" -gt 0 ]; then
            echo "$branch: behind $behind, ahead $ahead"
        fi
    fi
done

# 询问是否同步
read -p "Sync main branch? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    git checkout main
    git merge origin/main
fi

❓ 常见问题

Q fetch和pull应该用哪个?
A 推荐使用fetch。fetch更安全,可以先查看更新内容再决定是否合并。pull会自动合并,可能产生意外的冲突。养成先fetch再merge的习惯更好。
Q fetch会修改本地代码吗?
A 不会。fetch只下载更新到远程分支引用(如origin/main),不会修改当前分支和工作区。需要手动merge或rebase才会修改本地代码。
Q 如何查看fetch下载了什么?
A 使用 git log HEAD..origin/main 查看远程的新提交,使用 git diff HEAD origin/main 查看差异,使用 git diff --stat HEAD origin/main 查看统计。
Q fetch后如何合并?
A 使用 git merge origin/main 合并远程更新,或使用 git rebase origin/main 进行rebase合并。推荐使用rebase保持线性历史。
Q 如何清理已删除的远程分支引用?
A 使用 git fetch -pgit remote prune origin 清理本地过期的远程分支引用。这不会影响远程仓库,只是清理本地的引用。

📖 小节


📝 作业

  1. 基础题:在远程仓库创建新提交,本地使用fetch获取更新,查看远程的新提交和差异,然后手动合并。

  2. 进阶题:模拟Fork工作流:添加origin和upstream两个远程,从upstream fetch更新,查看差异,选择性合并到本地,然后推送到origin。

  3. 挑战题:编写一个脚本,定期fetch所有远程仓库,检查每个分支与远程的差异,生成同步报告,提示哪些分支需要同步。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏