搜索 K
主题
git remote、git fetch、git pull、git push 是 Git 分布式协作的核心命令。理解它们之间的关系和各自的行为,是团队协作开发的基础。
fetch 只下载不合并,pull = fetch + merge(或 rebase),push 将本地提交上传到远程。
| 区域 | 说明 | 命令操作 |
|---|---|---|
| 远程仓库 | GitHub/GitLab 上的仓库 | push 写入,fetch 读取 |
| 远程追踪分支 | origin/main 等,远程分支在本地的只读副本 | fetch 更新 |
| 本地分支 | main、feature 等 | merge/rebase 更新 |
| 工作目录 | 你实际编辑的文件 | checkout/switch 更新 |
origin/main 不是你能直接修改的分支。它是远程 main 的快照,只有 fetch 才会更新它。你的本地 main 是独立的,可能领先或落后于 origin/main。
# 查看远程仓库列表
git remote
# origin
# 查看详细信息(含 URL)
git remote -v
# origin https://github.com/user/repo.git (fetch)
# origin https://github.com/user/repo.git (push)
# 添加远程仓库
git remote add origin https://github.com/user/repo.git
git remote add upstream https://github.com/original/repo.git
# 修改远程仓库 URL
git remote set-url origin https://github.com/user/new-repo.git
# 修改远程仓库名称
git remote rename origin github
# 删除远程仓库
git remote remove upstream
# 查看远程仓库的详细信息
git remote show origin
# 显示:所有远程分支、追踪关系、push/fetch URL、过时的追踪引用# Fork 工作流中的典型配置
git remote -v
# origin https://github.com/myuser/repo.git (fetch) ← 你的 fork
# origin https://github.com/myuser/repo.git (push)
# upstream https://github.com/original/repo.git (fetch) ← 原始仓库
# upstream https://github.com/original/repo.git (push)
# 从原始仓库同步更新
git fetch upstream
git switch main
git merge upstream/main
git push origin main
# 部署到不同环境
git remote add staging https://git.heroku.com/app-staging.git
git remote add production https://git.heroku.com/app-production.git
git push staging main
git push production main# HTTPS(需要每次输入密码或使用 credential helper)
git remote set-url origin https://github.com/user/repo.git
# SSH(使用密钥认证,推荐)
git remote set-url origin git@github.com:user/repo.git
# 检查当前使用的协议
git remote -v
# 配置 credential helper(HTTPS 模式下缓存密码)
git config --global credential.helper store # 明文保存(不安全)
git config --global credential.helper cache # 内存缓存 15 分钟
git config --global credential.helper 'cache --timeout=3600' # 缓存 1 小时
# Windows 使用系统凭据管理器
git config --global credential.helper manager-core# 获取默认远程(origin)的所有更新
git fetch
# 获取指定远程
git fetch origin
git fetch upstream
# 获取指定分支
git fetch origin main
# 获取所有远程的更新
git fetch --all
# 获取并清理过时的远程追踪引用
git fetch --prune
# 如果远程的 feature/old 分支已删除,本地的 origin/feature/old 也会被清理
# 获取标签
git fetch --tags
git fetch origin --prune --prune-tags # 同步标签(删除远程没有的)# fetch 只更新远程追踪分支,不修改本地分支和工作目录
git fetch origin
# 查看 fetch 下来了什么
git log main..origin/main --oneline
# abc1234 feat: 远程的新提交
# def5678 fix: 远程的修复
# 查看远程比本地多了什么
git diff main origin/main --statfetch 永远不会修改你的工作目录或本地分支。它只是下载远程的最新状态到远程追踪分支。你可以随时 fetch,不用担心丢失本地修改。
# 浅克隆(只获取最近 N 个提交)
git clone --depth 1 https://github.com/user/repo.git
# 后续 fetch 只获取新的提交
# 加深浅克隆
git fetch --deepen 10 # 多获取 10 个提交
git fetch --unshallow # 转为完整克隆
# 部分克隆(按需下载文件内容)
git clone --filter=blob:none https://github.com/user/repo.git
# 只下载提交和树对象,文件内容在 checkout 时按需下载
# 只获取特定分支
git clone --single-branch --branch main https://github.com/user/repo.git# 拉取并合并当前分支的远程追踪分支
git pull
# 等价于:
# git fetch origin
# git merge origin/<当前分支>
# 拉取指定远程和分支
git pull origin main
# 使用 rebase 代替 merge
git pull --rebase
# 等价于:
# git fetch origin
# git rebase origin/<当前分支>
# 只允许 fast-forward 合并
git pull --ff-only
# 如果不能 fast-forward,会报错(而非创建合并提交)| 方式 | 历史结构 | 适用场景 |
|---|---|---|
pull(merge) | 保留分支结构 | 需要保留「谁在何时合并」的信息 |
pull --rebase | 线性历史 | 保持干净的提交历史(推荐) |
pull --ff-only | 只允许快进 | 最安全,冲突时拒绝而非静默合并 |
# 全局配置
git config --global pull.rebase true
# 或只对特定分支配置
git config --global branch.main.rebase true
# 如果 rebase 遇到冲突,可以用 --abort 取消
git rebase --abort# 问题 1:pull 时有未提交的修改
# error: Your local changes would be overwritten
# 解决:先 stash
git stash push -m "WIP"
git pull
git stash pop
# 问题 2:pull 产生了不必要的合并提交
# 使用 --rebase 避免
git pull --rebase
# 问题 3:pull 冲突
git pull
# CONFLICT!
# 解决冲突...
git add .
git commit # merge 模式
# 或
git rebase --continue # rebase 模式
# 放弃 pull
git merge --abort # merge 模式
git rebase --abort # rebase 模式# 推送当前分支到其追踪的远程分支
git push
# 推送到指定远程和分支
git push origin main
# 推送并设置追踪关系(首次推送时用)
git push -u origin feature/payment
# -u 等同于 --set-upstream
# 之后只需 git push 即可
# 推送所有分支
git push --all origin
# 推送标签
git push origin v2.0.0
git push origin --tags
git push origin --follow-tags # 只推送附注标签# ❌ 危险:覆盖远程历史
git push --force
git push -f
# ✅ 更安全的 force push
git push --force-with-lease
# 只有在远程分支没有被其他人更新时才允许强制推送
# 如果有人在你之后推送了新提交,这个命令会失败
# ✅✅ 最安全的 force push(Git 2.30+)
git push --force-with-lease --force-if-includes
# 额外确认你已经 fetch 了远程的最新状态main、develop 等共享分支绝对不能 force push--force-with-lease# 问题 1:push 被拒绝(远程有新提交)
# ! [rejected] main -> main (non-fast-forward)
# 解决:先 pull 再 push
git pull --rebase
git push
# 问题 2:没有远程追踪分支
# fatal: The current branch feature has no upstream branch.
# 解决:设置追踪
git push -u origin feature
# 问题 3:push 到受保护的分支
# remote: error: GH006: Protected branch update failed
# 解决:通过 Pull Request 合并
# 问题 4:push 的文件太大
# remote: error: File large-file.bin is 150.00 MB; exceeds 100 MB limit
# 解决:使用 Git LFS 或从历史中删除大文件
git lfs track "*.bin"
# 或
git filter-repo --strip-blobs-bigger-than 100M# 设置默认 push 行为
git config --global push.default current
# simple — 只推送当前分支到同名远程分支(默认,最安全)
# current — 推送当前分支到同名远程分支(即使没有追踪关系)
# upstream — 推送到追踪的上游分支
# matching — 推送所有同名分支(不推荐)
# 自动推送附注标签
git config --global push.followTags true
# 自动设置追踪关系
git config --global push.autoSetupRemote true
# Git 2.37+:首次 push 自动设置追踪,不需要 -u# 1. Fork 原始仓库到自己的 GitHub
# 2. 克隆自己的 fork
git clone https://github.com/myuser/repo.git
cd repo
# 3. 添加原始仓库为 upstream
git remote add upstream https://github.com/original/repo.git
# 4. 同步原始仓库的更新
git fetch upstream
git switch main
git rebase upstream/main
git push origin main
# 5. 创建 feature 分支并开发
git switch -c fix/typo-in-docs
vim docs/guide.md
git commit -am "docs: 修复文档中的错别字"
# 6. 推送到自己的 fork
git push -u origin fix/typo-in-docs
# 7. 在 GitHub 上创建 Pull Request
# fix/typo-in-docs → original/repo:main# 每天开始工作前
git switch main
git pull --rebase origin main
# 切到自己的功能分支
git switch feature/my-task
git rebase main # 同步最新的 main
# 工作中定期推送(备份 + 共享进度)
git push origin feature/my-task
# 如果 rebase 了需要 force push
git push --force-with-lease origin feature/my-task
# PR 合并后清理
git switch main
git pull origin main
git branch -d feature/my-task
git push origin --delete feature/my-task# 配置多个远程仓库对应不同环境
git remote add staging git@deploy:app-staging.git
git remote add production git@deploy:app-production.git
# 部署到 staging
git push staging main
# 部署到 production(从标签)
git push production v2.0.0:main
# 将本地的 v2.0.0 标签推送到 production 的 main 分支
# 查看各环境的部署状态
git remote show staging
git remote show production# 将仓库镜像到另一个服务器
git clone --mirror https://github.com/user/repo.git
cd repo.git
git remote add mirror https://gitlab.com/user/repo.git
git push --mirror mirror
# 定期同步
git fetch --all
git push --mirror mirror
# 或设置双推送
git remote set-url --add --push origin https://github.com/user/repo.git
git remote set-url --add --push origin https://gitlab.com/user/repo.git
# git push 同时推送到两个远程# 浅克隆(只需要最新代码,不需要完整历史)
git clone --depth 1 https://github.com/user/large-repo.git
# 单分支克隆(只需要某个分支)
git clone --single-branch --branch main https://github.com/user/repo.git
# 部分克隆(按需下载文件内容)
git clone --filter=blob:none https://github.com/user/repo.git
# 节省 90%+ 的克隆时间,文件在 checkout 时按需下载
# 稀疏检出(只需要部分目录)
git clone --filter=blob:none --sparse https://github.com/user/monorepo.git
cd monorepo
git sparse-checkout set src/api/ src/shared/
# 只检出 API 和共享代码目录# 从旧服务器迁移到新服务器(保留完整历史)
# 1. 完整克隆
git clone --mirror https://old-server.com/repo.git
cd repo.git
# 2. 修改远程指向
git remote set-url origin https://new-server.com/repo.git
# 3. 推送所有内容
git push --mirror origin
# 4. 通知团队更新远程 URL
# 团队成员执行:
git remote set-url origin https://new-server.com/repo.git# 列出远程分支
git branch -r
# 查看远程分支和本地分支的对应关系
git branch -vv
# 查看远程的所有引用(分支、标签、PR 等)
git ls-remote origin
# 查看远程 HEAD 指向
git ls-remote --symref origin HEAD
# 只看远程的标签
git ls-remote --tags origin
# 只看远程的分支
git ls-remote --heads origin# refspec 格式:<src>:<dst>
# fetch 时:远程的 src 映射到本地的 dst
# push 时:本地的 src 推送到远程的 dst
# 获取远程 main 到本地的 origin/main
git fetch origin main:refs/remotes/origin/main
# 推送本地 feature 到远程 develop
git push origin feature:develop
# 删除远程分支(推送空引用)
git push origin :feature/old
# 等价于
git push origin --delete feature/old
# 获取 GitHub PR 引用
git fetch origin pull/123/head:pr-123
git switch pr-123
# 在 .git/config 中配置自动获取 PR
[remote "origin"]
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
# 之后 git fetch 会自动获取所有 PR# 同时推送到多个远程
git remote set-url --add --push origin https://github.com/user/repo.git
git remote set-url --add --push origin https://gitlab.com/user/repo.git
git remote set-url --add --push origin https://bitbucket.org/user/repo.git
# 验证
git remote -v
# origin https://github.com/user/repo.git (fetch)
# origin https://github.com/user/repo.git (push)
# origin https://gitlab.com/user/repo.git (push)
# origin https://bitbucket.org/user/repo.git (push)
# git push 会同时推送到所有 push URL[alias]
# 拉取并 rebase
up = pull --rebase --prune
# 推送当前分支
pub = "!git push -u origin $(git branch --show-current)"
# 查看远程状态
rv = remote -v
# 同步 fork
sync = "!git fetch upstream && git rebase upstream/main && git push origin main"
# 查看领先/落后远程的提交数
ahead = "!git log origin/$(git branch --show-current)..HEAD --oneline"
behind = "!git log HEAD..origin/$(git branch --show-current) --oneline"# 配置 Git 在后台自动 fetch(Git 2.36+)
git config --global fetch.parallel 0 # 并行获取所有远程
git config --global maintenance.auto true
git config --global maintenance.strategy incremental
# 手动触发维护(包含 fetch)
git maintenance run --task=prefetch
# 或使用 cron / 系统定时任务
# 每 5 分钟自动 fetch
# */5 * * * * cd /path/to/repo && git fetch --all --prune --quiet# 推送前的检查清单
# 1. 确认当前分支
git branch --show-current
# 2. 确认推送目标
git remote -v
# 3. 预览将要推送的提交
git log origin/$(git branch --show-current)..HEAD --oneline
# 4. 推送
git push
# 配置 push 前自动运行测试
# .git/hooks/pre-push
#!/bin/bash
npm test || exit 1# push/fetch 超时
git config --global http.postBuffer 524288000 # 增大缓冲区(500MB)
git config --global http.lowSpeedLimit 1000 # 低速阈值
git config --global http.lowSpeedTime 60 # 低速超时
# 使用代理
git config --global http.proxy http://proxy:8080
git config --global https.proxy https://proxy:8080
# 只对特定域名使用代理
git config --global http.https://github.com.proxy socks5://127.0.0.1:1080
# 取消代理
git config --global --unset http.proxy# 大文件存储(Git Large File Storage)
git lfs install
# 跟踪大文件类型
git lfs track "*.psd"
git lfs track "*.mp4"
git lfs track "assets/**/*.bin"
# .gitattributes 自动生成
cat .gitattributes
# *.psd filter=lfs diff=lfs merge=lfs -text
# *.mp4 filter=lfs diff=lfs merge=lfs -text
git add .gitattributes
git commit -m "chore: 配置 Git LFS"
# push 时 LFS 文件会自动上传到 LFS 服务器
git push origin main
# 克隆时自动下载 LFS 文件
git clone https://github.com/team/project.git
# 如果不想下载 LFS 文件
GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/team/project.git
# 之后按需获取
git lfs pull --include="assets/needed-file.psd"# 场景:GitHub 宕机,需要临时切换到备用源
# 1. 查看当前远程配置
git remote -v
# 2. 临时切换到备用源
git remote set-url origin https://gitlab.com/team/repo.git
# 3. 紧急工作...
git pull
git push
# 4. GitHub 恢复后切回
git remote set-url origin https://github.com/team/repo.git
# 预防措施:提前配置备用远程
git remote add backup https://gitlab.com/team/repo.git
# 日常双推送
git push origin main
git push backup main# 大型开源项目中,多个团队基于同一仓库工作
# 添加多个 fork 作为远程
git remote add upstream https://github.com/original/repo.git
git remote add team-a https://github.com/team-a/repo.git
git remote add team-b https://github.com/team-b/repo.git
# 获取所有团队的工作
git fetch --all
# 查看 team-a 的某个功能分支
git log team-a/feature/new-api --oneline -10
# 基于 team-a 的分支继续开发
git switch -c feature/extend-api team-a/feature/new-api
# cherry-pick team-b 的某个修复
git cherry-pick team-b/fix/critical-bug~0# 在没有网络的环境中传输 Git 数据
# 创建 bundle(包含完整仓库)
git bundle create repo.bundle --all
# 创建部分 bundle(只包含某些分支/提交范围)
git bundle create update.bundle main ^origin/main
# 只打包本地 main 比远程 main 多出的提交
# 在另一台机器上使用 bundle
git clone repo.bundle project/
# 或
git pull update.bundle main
# 验证 bundle 完整性
git bundle verify repo.bundle
# 适用场景:
# - 安全隔离环境(无网络)
# - 超大仓库的初始传输(比 clone 快,可用 USB)
# - 备份# 查看传输统计
GIT_TRACE=1 git fetch origin 2>&1 | grep -E "pack|objects"
# remote: Counting objects: 42, done.
# remote: Compressing objects: 100% (30/30), done.
# remote: Total 42 (delta 15), reused 35 (delta 10)
# Receiving objects: 100% (42/42), 12.5 KiB, done.
# Resolving deltas: 100% (15/15), done.
# Git 使用智能协议优化传输:
# 1. 客户端告诉服务端已有哪些对象
# 2. 服务端只发送差异(delta compression)
# 3. 使用 packfile 格式压缩传输# 远程追踪分支存储在
ls .git/refs/remotes/origin/
# main
# feature/payment
# HEAD
# 或压缩在 packed-refs 中
grep "refs/remotes" .git/packed-refs
# fetch 更新这些引用,但不会触碰 refs/heads/(本地分支)
# 这就是为什么 fetch 是安全的
# FETCH_HEAD 文件记录最近一次 fetch 的结果
cat .git/FETCH_HEAD
# abc1234... branch 'main' of https://github.com/team/repo
# def5678... not-for-merge branch 'feature' of https://github.com/team/repo# 写入项目 CONTRIBUTING.md 或 README
# === 必须配置 ===
git config pull.rebase true # pull 默认 rebase
git config push.autoSetupRemote true # 自动设置追踪(Git 2.37+)
git config fetch.prune true # fetch 时自动清理
git config push.followTags true # push 时自动推送附注标签
# === 推荐配置 ===
git config rerere.enabled true # 记住冲突解决方案
git config diff.submodule log # 显示子模块变更详情
git config status.submoduleSummary true # status 显示子模块摘要
# === 一键脚本 ===
#!/bin/bash
# setup-git.sh — 新成员加入时运行
git config pull.rebase true
git config push.autoSetupRemote true
git config fetch.prune true
git config push.followTags true
git config rerere.enabled true
echo "✅ Git 配置完成"# GitHub Actions 中的远程操作注意事项
# 1. 使用 token 而非 SSH(更简单)
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0 # 完整历史(bisect/tag 需要)
# 2. 推送时使用 bot 身份
- name: Push changes
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git push origin main
# 3. 跨仓库操作需要 PAT
- uses: actions/checkout@v4
with:
repository: team/other-repo
token: ${{ secrets.PAT_TOKEN }}git pull 时不加 --rebase 导致历史混乱# ❌ 频繁 pull 产生大量合并提交
git pull # 每次都会创建 "Merge branch 'main' of ..."
# ✅ 配置默认 rebase
git config --global pull.rebase true
# 之后 git pull 自动使用 rebase# ❌ 覆盖了团队成员的提交
git push -f origin main
# ✅ 只在个人分支上 force push
git push --force-with-lease origin feature/my-task
# ✅✅ 配置 Git 拒绝 force push 到受保护分支
# 在 GitHub/GitLab 的分支保护规则中启用# ❌ 每次都要完整写
git push origin feature/payment
# ✅ 首次 push 时设置 upstream
git push -u origin feature/payment
# 之后只需
git push
# ✅✅ 配置自动设置(Git 2.37+)
git config --global push.autoSetupRemote true# 浅克隆后 log 只能看到有限历史
git clone --depth 1 <url>
git log # 只有 1 个提交!
# 需要时转为完整克隆
git fetch --unshallow# ❌ 不安全
git config --global credential.helper store
# 密码明文保存在 ~/.git-credentials
# ✅ 使用 SSH 密钥
git remote set-url origin git@github.com:user/repo.git
# ✅ 或使用系统凭据管理器
# Windows
git config --global credential.helper manager-core
# macOS
git config --global credential.helper osxkeychainfetch 和 pull 的区别是什么?| 对比 | fetch | pull |
|---|---|---|
| 下载 | ✅ | ✅ |
| 合并 | ❌ | ✅(merge 或 rebase) |
| 安全性 | 完全安全 | 可能产生冲突 |
| 适用场景 | 查看远程有什么更新 | 将远程更新合并到本地 |
# 方式 1:revert(安全,推荐用于共享分支)
git revert HEAD
git push
# 方式 2:reset + force push(只用于个人分支)
git reset --hard HEAD~1
git push --force-with-leasegit fetch upstream
git switch main
git rebase upstream/main
git push origin mainorigin 是什么?可以改名吗?origin 是默认的远程仓库名称(git clone 时自动创建)。可以改名但不推荐:
git remote rename origin github# 先更新远程信息
git fetch
# 查看状态
git status
# Your branch is ahead of 'origin/main' by 3 commits.
# 或
git branch -vv
# main abc1234 [origin/main: ahead 3, behind 2]
# 查看具体的提交
git log origin/main..HEAD --oneline # 领先的提交
git log HEAD..origin/main --oneline # 落后的提交# 设置 SSH 密钥路径
$env:GIT_SSH_COMMAND = "ssh -i C:\Users\admin\.ssh\id_ed25519"
# 或永久配置
git config --global core.sshCommand "ssh -i C:/Users/admin/.ssh/id_ed25519"| 目标 | 命令 |
|---|---|
| 查看远程列表 | git remote -v |
| 添加远程 | git remote add <name> <url> |
| 修改 URL | git remote set-url <name> <url> |
| 重命名 | git remote rename <old> <new> |
| 删除 | git remote remove <name> |
| 查看详情 | git remote show <name> |
| 目标 | 命令 |
|---|---|
| 获取默认远程 | git fetch |
| 获取指定远程 | git fetch <remote> |
| 获取所有远程 | git fetch --all |
| 获取并清理 | git fetch --prune |
| 获取标签 | git fetch --tags |
| 浅获取 | git fetch --depth N |
| 获取 PR 引用 | git fetch origin pull/N/head:pr-N |
| 目标 | 命令 |
|---|---|
| 拉取并合并 | git pull |
| 拉取并 rebase | git pull --rebase |
| 只允许 fast-forward | git pull --ff-only |
| 指定远程和分支 | git pull <remote> <branch> |
| 目标 | 命令 |
|---|---|
| 推送当前分支 | git push |
| 推送并设置追踪 | git push -u origin <branch> |
| 推送所有分支 | git push --all |
| 推送标签 | git push --tags |
| 推送附注标签 | git push --follow-tags |
| 安全强制推送 | git push --force-with-lease |
| 删除远程分支 | git push origin --delete <branch> |