Appearance
数据拉取与推送
远程仓库的数据同步是团队协作的核心操作,包括拉取(fetch/pull)和推送(push)。
git fetch:仅拉取,不合并
git fetch 从远程仓库下载新数据,但不修改本地工作区和当前分支:
bash
# 拉取默认远程仓库(origin)的所有分支
git fetch
# 拉取指定远程仓库
git fetch origin
# 拉取所有远程仓库
git fetch --all
# 拉取特定分支
git fetch origin main
git fetch origin feature/login
# 拉取并清理已删除的远程分支(见后面章节)
git fetch --prune
git fetch -p # 简写fetch 之后需要手动合并:
bash
git fetch origin
git log HEAD..origin/main --oneline # 查看有哪些新提交
git merge origin/main # 合并到当前分支
# 或
git rebase origin/mainfetch 的优势:
- 安全:不会改变本地工作状态
- 可以先查看远程改动再决定如何合并
- 更新所有远程追踪分支(origin/*)
git pull:拉取并合并
git pull 是 git fetch + git merge 的组合:
bash
# 拉取并合并(默认:fetch + merge)
git pull
# 拉取指定分支
git pull origin main
# 等价于:
git fetch origin main
git merge origin/maingit pull --rebase:拉取并变基
bash
# 拉取并用 rebase 代替 merge
git pull --rebase
git pull --rebase origin main
# 等价于:
git fetch origin
git rebase origin/main优点: 保持线性历史,避免产生不必要的合并提交
推荐配置: 将 rebase 设为 pull 的默认行为:
bash
git config --global pull.rebase truepull --rebase 的工作原理:
远程:A ← B ← C(新提交)
本地:A ← D(本地提交)
git pull --rebase 后:
A ← B ← C ← D'(D 被重新应用到 C 之后)git push:推送到远程
bash
# 推送当前分支到远程同名分支
git push
# 推送到指定远程和分支
git push origin main
git push origin feature/login
# 推送所有分支
git push --all origingit push -u:设置上游追踪
首次推送新分支时,使用 -u 设置追踪关系:
bash
# 推送并设置 upstream(上游追踪)
git push -u origin feature/login
git push --set-upstream origin feature/login
# 设置后,后续直接 git push/pull 即可
git push
git pull追踪关系的作用:
git push不带参数时,知道推送到哪里git pull不带参数时,知道从哪里拉取git status显示与追踪分支的领先/落后关系
git push --force vs --force-with-lease
--force(危险!)
强制推送,直接覆盖远程分支,不管远程是否有新提交:
bash
git push --force
git push -f # 简写风险: 如果有人在你之后推送了提交,你的 force push 会直接覆盖他们的工作!
--force-with-lease(推荐)
更安全的强制推送:只有当远程与你预期的状态一致时,才允许推送:
bash
git push --force-with-lease
git push --force-with-lease origin main如果远程在你最后一次 fetch 之后有新提交,--force-with-lease 会拒绝推送并报错,避免覆盖他人的工作。
什么时候需要 force push?
- 修改了已推送的提交(amend)
- 对功能分支进行了 rebase
- 清理了提交历史(interactive rebase)
黄金法则: 永远不要对共享分支(main、develop)进行 force push!
git push --tags:推送标签
bash
# 推送所有本地标签
git push --tags
git push origin --tags
# 推送单个标签
git push origin v1.0.0
# 不推送标签(默认 push 不包含标签)
git push # 默认不推送标签git push 删除远程分支
bash
# 删除远程分支(新语法)
git push origin --delete feature/login
# 删除远程分支(旧语法,等价)
git push origin :feature/login
# 删除远程标签
git push origin --delete v1.0.0
git push origin :refs/tags/v1.0.0推送配置
bash
# 设置默认 push 行为(只推送当前分支对应的远程分支)
git config --global push.default current
# simple - 只推送有追踪关系的同名分支(2.0+ 默认)
# current - 推送到同名分支(无论是否设置追踪)
# upstream - 推送到上游分支(可以不同名)
# matching - 推送所有有对应关系的分支(旧默认)
# nothing - 不推送任何东西(需要明确指定)
# 自动设置追踪(推送时自动 -u)
git config --global push.autoSetupRemote true # Git 2.37+实用场景
首次发布项目
bash
git init -b main
git add .
git commit -m "Initial commit"
git remote add origin git@github.com:user/repo.git
git push -u origin main日常工作流
bash
# 开始工作前同步
git pull --rebase
# 完成功能后推送
git push
# 推送新功能分支
git switch -c feature/new-feature
# 开发...
git push -u origin feature/new-feature推送前检查
bash
# 检查本地与远程的差异
git fetch
git log origin/main..HEAD --oneline # 查看将要推送的提交
# 确认无误后推送
git push处理推送冲突
bash
# 推送时提示:
# ! [rejected] main -> main (non-fast-forward)
# hint: Updates were rejected because the tip of your current branch is behind
# hint: its remote counterpart.
# 解决方案1:先拉取,再推送
git pull --rebase
git push
# 解决方案2(只有个人分支):force push
git push --force-with-lease理解 fetch 和 pull 的区别
远程仓库
/ \
fetch \
/ \
origin/main (网络)
|
merge/rebase
|
HEAD(本地分支)
pull = fetch + merge/rebase(一步完成)建议养成的习惯: 优先使用 git fetch + 手动合并,这样可以在合并前查看远程的改动,做出更明智的决策。
总结
| 操作 | 命令 | 说明 |
|---|---|---|
| 只拉取不合并 | git fetch | 安全,不修改工作区 |
| 拉取并合并 | git pull | fetch + merge |
| 拉取并变基 | git pull --rebase | fetch + rebase,保持线性 |
| 推送 | git push | 推送到追踪分支 |
| 首次推送设追踪 | git push -u origin <branch> | 设置追踪关系 |
| 安全强制推送 | git push --force-with-lease | 优于 git push -f |
| 删除远程分支 | git push origin --delete <branch> | |
| 推送标签 | git push --tags |