Git 版本控制核心操作详解与实战指南
远程分支管理与切换
当需要切换到一个本地尚不存在的远程分支时,首先需要更新远程仓库索引,然后基于远程分支创建本地分支并检出。例如,切换到名为 feature-login 的远程分支:
git fetch upstream
git checkout -b feature-login upstream/feature-login
若要直接修改远程仓库地址,可以使用 set-url 命令;若需修改当前分支的跟踪目标,则使用 --set-upstream-to:
git remote set-url origin https://repo.new-address.com/project.git
git branch --set-upstream-to=origin/main main
代码差异对比
Git 提供了强大的 Diff 工具来比较不同分支或提交之间的差异。
# 显示 branchA 和 branchB 之间所有文件的详细差异
git diff branchA branchB
# 仅显示有差异的文件列表及统计信息
git diff branchA branchB --stat
# 查看指定文件(如 src/utils.js)在两个分支间的差异
git diff branchA branchB src/utils.js
代码仓库迁移
将代码从一个仓库迁移到另一个仓库,同时保留完整的提交历史和分支信息,可以按照以下步骤操作:
# 1. 将现有的 origin 远程仓库重命名为 old-origin
git remote rename origin old-origin
# 2. 添加新的远程仓库地址
git remote add origin https://new-repo.url/git.git
# 3. 推送所有分支内容到新仓库
git push origin --all
# 4. 推送所有标签
git push origin --tags
# 5. 针对本地剩余的多个分支,分别切换并推送
git checkout dev-branch
git push origin dev-branch
分支与常用操作指令
HEAD 指针始终指向当前所在的提交。以下是日常开发中高频使用的 Git 指令:
git version # 查看当前 Git 版本
git branch # 列出本地分支
git branch -r # 列出所有远程分支
git branch -a # 列出所有本地和远程分支
git branch -d legacy-branch # 删除指定的本地分支
git branch -m old-name new-name # 重命名本地分支
git checkout new-branch # 切换到已存在的分支
git checkout -b hotfix # 创建新分支并立即切换
git checkout -- src/app.js # 撤销工作区中指定文件的修改(回滚到暂存区状态)
同步与远程交互
git pull origin main:main # 拉取远程 main 分支并合并到本地 main
git push origin -d feature-x # 删除远程仓库中的 feature-x 分支
git fetch --prune # 更新分支列表,并清理本地已失效的远程分支引用
git status # 查看工作区与暂存区状态
暂存与提交 (Staging & Committing)
提交代码是将修改记录到版本库的关键步骤。
git add src/config.js # 将指定文件添加到暂存区
git commit -m 'fix typo' # 提交暂存区内容,并附上说明(不推荐在复杂场景使用)
git commit -am 'fix typo' # 跳过 git add,直接提交所有已跟踪文件的修改
git commit ./src/helper.js # 将 add 和 commit 两步合二为一(推荐使用)
在使用不带 -m 参数的 git commit 时,会进入文本编辑器(如 Vim)。这种方式能让你在提交前查看本次修改涉及的文件和分支信息,便于检查并撤销错误的提交,比直接使用命令行参数更安全。
git commit --amend # 修改最后一次提交(合并暂存区修改到上一次提交)
工作现场保存 (Stash)
当需要临时切换上下文但不想提交当前未完成的代码时,可以使用 Stash。
git stash # 将当前工作现场压栈保存
git stash pop # 恢复最近一次保存的工作现场,并从栈中删除该记录
合并与拉取策略
git fetch --all # 获取所有远程仓库的更新
git merge origin/main # 将远程 main 分支合并到当前分支
git merge --abort # 终止当前的合并操作,恢复到合并前的状态
git pull origin main # 拉取并合并(等同于 fetch + merge)
注意:直接使用 git pull 可能会产生不必要的合并提交。更安全的做法是先 fetch,检查差异后再决定是否 merge。
提交历史查询
git log src/main.js # 查看指定文件的提交记录
git log -p src/main.js # 查看指定文件每次提交的具体差异
git log --pretty=oneline # 单行显示提交历史(哈希值+说明)
git log --graph # 以图形化方式展示分支合并历史
版本回退与 Reset 模式详解
Git 中 reset 命令用于回退版本,其三种模式对工作区和暂存区的影响各不相同。
git reset --hard HEAD~1 # 回退到上一个版本:彻底丢弃工作区和暂存区的所有修改
git reset --soft HEAD~1 # 回退到上一个版本:保留修改,并将修改内容放入暂存区
git reset --mixed HEAD~1 # (默认模式)回退:保留修改内容在工作区,但清空暂存区
模式对比:
- --hard: 指针移动,暂存区清空,工作区清空。非常危险,除非确定要丢弃所有更改。
- --soft: 仅移动 HEAD 指针。所有修改保留在暂存区,相当于撤销了
commit,准备重新提交。 - --mixed: 移动 HEAD 指针,清空暂存区。修改保留在工作区(未暂存状态),相当于撤销了
commit和add。
引用符号 ^ 与 ~ 的区别
在指定父提交时,这两个符号含义不同:
HEAD^n # 指 HEAD 的第 n 个父提交(在合并提交时有效,如 HEAD^2 指第二个父节点)
HEAD~n # 指 HEAD 的第 n 级祖先提交(沿第一父节点回溯 n 次)
例如:HEAD~2 等同于 HEAD^1^1,即父节点的父节点。
配置管理 (Config)
Git 配置分为三个层级:本地(当前仓库)、全局(当前用户)和系统。
# 查看配置
git config --local -l # 查看当前仓库配置
git config --global -l # 查看用户全局配置
# 编辑配置
git config --global -e # 编辑全局配置文件(如 .gitconfig)
# 修改配置项
git config --global core.editor vim # 设置默认编辑器
git config --global push.default current # 设置默认推送行为
# 增加配置项
git config --add alias.st status
# 获取与删除
git config --get user.name
git config --global --unset user.email
变基 与 撤销
Rebase 用于整理提交历史,使其更加线性。
git rebase main # 将当前分支的提交基于 main 分支重新应用
git rebase -i HEAD~3 # 交互式变基,修改最近 3 次提交(squash, reword, edit 等)
在交互界面中,将 pick 改为 edit 可以修改对应提交,完成后使用 git rebase --continue 继续。
git rebase --onto HEAD HEAD^1 feature-branch # 移除指定提交
git push origin feature-branch -f # 强制推送(需谨慎,通常用于变基后)
Revert 与 rebase 删除提交不同,revert 是创建一个新的"反向提交"来抵消旧的提交。这种方式不会改变历史记录,更安全。
git revert HEAD # 撤销最后一次提交,并生成新的提交记录
数据恢复:Reflog
如果误操作导致提交丢失(如 hard reset),reflog 是救命稻草。它记录了 HEAD 的所有移动轨迹。
git reflog show --date=iso main # 查看 main 分支的操作时间线
git checkout c08de9a # 检出到丢失提交的哈希值
git checkout -b recovered-branch # 基于该提交重建分支
注意:Git 会定期清理不可达的对象,因此恢复操作必须及时。
标签管理
标签常用于标记发布版本。
git tag # 列出所有标签
git tag -l "v1.*" # 列出匹配模式的标签
git tag v1.0.0 # 创建轻量标签
git tag -a v2.0.0 -m "Release v2.0.0" # 创建附注标签(包含信息)
git tag -d v1.0.0 # 删除本地标签
git checkout v1.0.0 # 检出到特定标签状态