Git
以下是 Git 常用操作的整理
一、基础配置(首次使用必做)
# 配置用户名和邮箱(关联远程仓库提交记录)
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"
# 查看配置信息
git config --list
SSH
绑定 SSH 密钥到 Git 仓库(如 GitHub、GitLab 等)可以实现免密码拉取和推送代码,且使用 SSH 更加稳定,操作步骤如下:
一、检查是否已有 SSH 密钥
首先查看本地是否已存在 SSH 密钥(避免重复创建):
# 进入 SSH 密钥目录
cd ~/.ssh
# 列出目录下的文件
ls
若看到 id_rsa(私钥)和 id_rsa.pub(公钥),说明已有密钥,可直接跳到步骤三。
二、生成新的 SSH 密钥
若没有密钥,执行以下命令生成(一路回车,无需设置密码,除非需要额外安全验证):
# 替换为你的 Git 绑定邮箱
ssh-keygen -t ed25519 -C "your_email@example.com"
- 若系统不支持
ed25519算法,可使用旧算法:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
执行后会在 ~/.ssh 目录下生成 id_ed25519(或 id_rsa)和 id_ed25519.pub(或 id_rsa.pub)文件。
三、查看并复制公钥内容
需要将公钥(.pub 文件)的内容添加到 Git 仓库:
# 查看公钥内容(以 ed25519 为例,若用 rsa 则替换为 id_rsa.pub)
cat ~/.ssh/id_ed25519.pub
输出类似如下内容,完整复制从 ssh-ed25519 开始到邮箱结束的所有字符:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK5cR44xQJz8G9xQZQZQZQZQZQZQZQZQZQZQZQZQZ your_email@example.com
四、在 Git 仓库中添加 SSH 公钥
以 GitHub 为例(其他平台如 GitLab、Gitee 步骤类似):
- 登录 GitHub,点击右上角头像 → Settings;
- 在左侧菜单找到 SSH and GPG keys → 点击 New SSH key;
- 在 Title 中填写一个标识(如“我的笔记本”);
- 在 Key 中粘贴刚才复制的公钥内容;
- 点击 Add SSH key,完成添加。
五、验证 SSH 连接
添加后,验证是否绑定成功:
# 针对 GitHub 的验证命令
ssh -T git@github.com
# 针对 GitLab 的验证命令
ssh -T git@gitlab.com
# 针对 Gitee 的验证命令
ssh -T git@gitee.com
首次连接会提示确认,输入 yes 回车。若看到类似以下信息,说明绑定成功:
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
六、修改仓库远程地址为 SSH 格式(若之前用 HTTPS)
如果之前仓库是用 HTTPS 地址克隆的,需修改为 SSH 地址才能使用 SSH 密钥:
# 查看当前远程地址
git remote -v
# 修改远程地址为 SSH 格式(以 GitHub 为例)
git remote set-url origin git@github.com:username/repo.git
SSH 格式的仓库地址一般为:git@域名:用户名/仓库名.git(可在仓库页面的 Clone 按钮中获取)。
注意事项
- 私钥(
id_rsa或id_ed25519)是核心凭证,切勿泄露给他人; - 一台设备只需生成一次 SSH 密钥,可绑定到多个 Git 仓库;
- 若更换设备,需要重新生成并添加新的 SSH 密钥。
绑定完成后,后续操作 git pull、git push 就无需输入密码了。
二、克隆
# 克隆远程仓库到本地(默认拉取所有分支)
git clone <远程仓库地址> # 例如:git clone https://github.com/username/repo.git
# 克隆后进入仓库目录
cd <仓库名>
# 查看远程仓库信息(确认关联的远程地址)
git remote -v
三、本地提交与推送
1. 新建文件/修改后提交
# 查看工作区文件状态(哪些文件被修改/新增/删除)
git status
# 将文件添加到暂存区(. 表示所有修改,也可指定文件名)
git add . # 或 git add <文件名>
# 提交暂存区文件到本地仓库,-m 后跟提交说明(必填)
git commit -m "提交说明:例如修复登录bug、新增首页组件等"
2. 推送到远程仓库
# 首次推送当前分支到远程(需指定远程仓库名和分支名,通常远程名为origin)
git push -u origin <分支名> # 例如:git push -u origin main
# 非首次推送(已关联远程分支后)
git push
3. 拉取远程最新代码(避免冲突)
# 拉取远程当前分支的最新代码并合并到本地
git pull
# 等价于 git fetch(拉取远程更新但不合并) + git merge(合并到本地)
git fetch origin <分支名>
git merge origin/<分支名>
将本地当前分支推送到远程仓库的指定分支
要将本地当前分支推送到远程仓库的指定分支,可以使用 git push 命令并指定远程仓库名称和目标分支名。具体操作如下:
# 推送本地当前分支到远程的指定分支
git push <远程仓库名> <本地当前分支名>:<远程目标分支名>
常见场景示例:
- 默认远程仓库(origin)的情况:
通常远程仓库默认名称为 origin,如果要将本地当前分支 dev 推送到远程的 test 分支:
git push origin dev:test
- 本地分支与远程目标分支名称相同:
若要推送本地 main 分支到远程同名的 main 分支(最常用场景):
git push origin main:main
# 简化写法(当本地分支与远程目标分支同名时)
git push origin main
- 首次推送并关联分支:
如果是第一次推送该分支到远程,且希望后续可直接用 git push 推送,可以加上 -u 参数关联分支:
git push -u origin 本地分支名:远程目标分支名
# 示例:将本地feature分支首次推送到远程的beta分支并关联
git push -u origin feature:beta
注意事项:
- 推送前建议先执行
git pull拉取远程目标分支的最新代码,避免冲突。 - 如果远程目标分支不存在,该命令会自动在远程创建这个分支。
- 若推送失败(如提示权限不足或分支保护),需检查远程仓库的访问权限或分支规则。
四、分支操作
在 Git 中,分支(Branch) 可以允许你在不影响主代码的情况下,独立开发新功能、修复 bug 或尝试实验性改动。
举例:你正在写一篇论文(主分支),突然想加一个新章节,但又怕写坏了影响正文。这时你可以复印一份论文(创建分支),在复印件上随意修改。满意后,再把修改的部分合并到原文里;如果不满意,直接丢掉复印件即可,原文不会受任何影响。
为什么需要分支?
- 隔离开发:多人协作时,每个人在自己的分支开发,互不干扰(比如甲开发支付功能,乙开发登录功能)。
- 保护主代码:主分支(通常叫
main或master)保持稳定可运行,新功能在分支上完成测试后再合并。 - 灵活实验:可以在分支上尝试激进的改动,失败了直接删除分支即可,不影响主代码。
- 版本管理:不同分支可以对应不同版本(比如
v1.0分支修复旧版本 bug,v2.0分支开发新功能)。
分支的核心概念
- 主分支(Main/Master):项目的 “正式版本” 分支,通常存放可发布的代码。
- 功能分支(Feature Branch):为开发新功能创建的分支(如
feature/payment)。 - bugfix 分支:为修复特定 bug 创建的分支(如
bugfix/login-error)。 - 分支指针:Git 用一个叫
HEAD的指针标记当前所在的分支,切换分支就是移动这个指针。
举个通俗例子
假设团队开发一个购物网站:
- 初始时只有
main分支,包含基础的商品展示功能。 - 开发者 A 想加 “购物车” 功能,创建
feature/cart分支,在这个分支上写代码,main分支不受影响。 - 同时开发者 B 发现商品展示有 bug,创建
bugfix/display分支修复,不干扰 A 的工作。 - A 完成后,把
feature/cart合并到main,购物车功能正式上线。 - B 修复后,把
bugfix/display合并到main,bug 被修复。
整个过程中,main 分支始终保持可运行状态,且 A 和 B 的工作互不冲突。
分支的本质(简单技术视角)
Git 的分支本质上是一个 “指针”,指向某个提交记录(代码快照)。创建分支时,Git 不会复制整个项目文件,只会新建一个指针,因此分支操作非常轻量(毫秒级完成)。
比如:
- 你在
main分支有 10 次提交,创建dev分支后,dev指针和main指针指向同一个提交。 - 当你在
dev上做新提交,dev指针会向前移动,而main指针保持不变,形成两条平行的提交历史。
用法示例
# 查看所有分支(本地+远程,*表示当前分支)
git branch -a
# 创建新分支并切换到该分支
git checkout -b <新分支名> # 或 git switch -c <新分支名>(Git 2.23+)
# 切换到已有分支
git checkout <分支名> # 或 git switch <分支名>
# 删除本地分支(确保已合并,未合并需加 -D 强制删除)
git branch -d <分支名> # 安全删除(需合并)
git branch -D <分支名> # 强制删除(未合并也可删)
# 删除远程分支
git push origin --delete <远程分支名>
# 将本地分支推送到远程(创建远程分支)
git push -u origin <本地分支名>
#合并目标分支(如 feature/login)到当前分支
git merge feature/login
五、cherry-pick(选择性合并提交)
用于将某分支的单个或多个特定提交合并到当前分支(无需合并整个分支)。
# 1. 先查看目标分支的提交记录,获取需要合并的提交哈希(前6-8位即可)
git log <目标分支名> # 例如:git log feature/login
# 输出类似:commit a1b2c3d4...(哈希值),复制该哈希
# 2. 切换到需要接收提交的分支
git checkout <目标分支> # 例如:git checkout main
# 3. 执行cherry-pick,合并指定提交
git cherry-pick <提交哈希> # 例如:git cherry-pick a1b2c3d4
# 4. 若出现冲突,解决后执行:
git add . # 标记冲突已解决
git cherry-pick --continue # 完成cherry-pick
# 若放弃操作:git cherry-pick --abort
适用场景:修复 bug 后,需将修复提交同步到多个分支(如 main、test 分支)。
安全的 cherry-pick 处理
cherry-pick 本质是将其他提交的代码合并到当前分支,可能引入冲突或逻辑问题。
一、操作前:进行备份
在执行 cherry-pick 前,先为当前分支创建“备份”,确保即使操作出错也能回退到原始状态:
# 1. 查看当前分支状态,确保工作区干净(无未提交的修改)
git status # 若有未提交的修改,先 commit 或 stash 保存
# 2. 为当前分支创建一个“备份分支”(命名清晰,如 backup/before-cherrypick)
git branch backup/before-cherrypick
这样,即使 cherry-pick 后代码混乱,也能通过 git checkout backup/before-cherrypick 回到操作前的状态。
二、执行 cherry-pick 时:逐步验证
- 先查看目标提交的具体内容,确认是否真的需要合并:
# 查看目标提交的修改内容(哈希值从目标分支的 git log 中获取)
git show <提交哈希> # 例如:git show a1b2c3d4
- 执行 cherry-pick 并观察结果:
git cherry-pick <提交哈希>
- 若成功:终端会显示
[当前分支 xxxxxxx]提示,直接进入步骤 3 验证。 - 若失败(出现冲突):终端会提示
error: could not apply xxxxxxx...,此时进入“冲突处理”流程(见下文)。
三、操作后:验证代码正确性
无论是否出现冲突,cherry-pick 后都必须验证代码:
- 检查代码逻辑:打开被修改的文件,确认合并后的代码是否符合预期(比如没有多余的代码、条件判断是否正确)。
- 本地测试:运行项目,测试相关功能是否正常(比如编译是否通过、接口是否能正常调用)。
- 查看提交记录:确认 cherry-pick 生成的新提交是否正确:
git log --oneline -3 # 查看最近3条提交记录
四、如果出问题:如何回退?
如果发现 cherry-pick 后的代码有问题,可根据不同阶段快速恢复:
1. 尚未解决冲突(处于 cherry-pick 过程中)
若 cherry-pick 时出现冲突,且你不想继续处理,可直接终止操作,回到执行前的状态:
git cherry-pick --abort # 放弃当前 cherry-pick,恢复到操作前的状态
2. 已完成 cherry-pick 但未推送到远程
如果已完成 cherry-pick 并生成了新提交,但测试发现问题:
# 撤销最近一次提交(即 cherry-pick 生成的提交),保留代码修改
git reset --soft HEAD~1
# 此时代码会回到 cherry-pick 后的状态,可手动修改或放弃:
# 若想彻底放弃所有修改,回到备份分支的状态:
git reset --hard backup/before-cherrypick
3. 已推送到远程
如果已将 cherry-pick 的结果推送到远程,此时回退需要“撤销提交”并强制推送(需确保团队成员知晓,避免影响他人):
# 1. 本地撤销提交(生成一个新的“撤销提交”)
git revert <cherry-pick生成的提交哈希>
# 2. 推送到远程,覆盖错误的提交
git push origin <当前分支名>
五、更安全的方案:临时分支验证
如果对 cherry-pick 的代码完全不放心,可先在“临时分支”中验证,确认无误后再合并到目标分支:
# 1. 基于当前分支创建临时分支
git checkout -b temp/cherrypick-test
# 2. 在临时分支中执行 cherry-pick
git cherry-pick <提交哈希>
# 3. 在临时分支中测试代码,确认无误后
git checkout <目标分支> # 切回原分支
git merge temp/cherrypick-test # 将临时分支的修改合并过来
# 4. 验证后删除临时分支
git branch -d temp/cherrypick-test
六、冲突处理
当多人修改同一文件的同一部分,或合并分支/拉取代码时,可能出现冲突。
1. 冲突表现
执行 git pull 或 git merge 后,终端提示 Automatic merge failed; fix conflicts and then commit the result.
2. 解决步骤
# 1. 查看冲突文件(终端会显示哪些文件冲突)
git status # 冲突文件会标记为 "both modified"
# 2. 打开冲突文件,寻找冲突标记并修改
# 文件中冲突部分会被标记:
# <<<<<<< HEAD(当前分支的代码)
# 你的代码
# =======
# 对方的代码
# >>>>>>> 分支名/提交哈希(合并过来的代码)
# 3. 手动编辑文件,保留正确代码,删除冲突标记(<<<<<<<, =======, >>>>>>>)
# 4. 标记冲突已解决
git add <冲突文件名> # 或 git add .(所有文件)
# 5. 完成合并提交(merge冲突时需要)
git commit -m "解决合并冲突:保留xxx逻辑"
# (若为pull冲突,此步可省略,pull会自动提交)
少量冲突可以使用 vim 快速处理,大量冲突可以使用 vscode 更直观方便地处理
七、其他常用操作
1. 撤销操作
# 撤销工作区修改(未git add的文件)
git checkout -- <文件名> # 慎用!会丢失未提交的修改
# 撤销暂存区修改(已git add但未commit)
git reset HEAD <文件名> # 回到工作区
# 撤销本地提交(保留修改,回到暂存区)
git reset --soft HEAD~1 # HEAD~1表示撤销最近1次提交,~2撤销2次
# 彻底撤销本地提交(丢弃修改,谨慎使用!)
git reset --hard HEAD~1
2. 查看提交记录
# 简洁查看提交历史(一行一条)
git log --oneline
# 查看分支合并图(直观展示分支关系)
git log --graph --oneline --all
# 查看某个文件的修改历史
git log <文件名>
3. 暂存工作区(stash)
用于临时保存工作区修改,切换分支时不提交代码。
# 暂存当前工作区修改
git stash
# 查看所有暂存记录
git stash list
# 恢复最近的暂存记录(并删除暂存)
git stash pop
# 恢复指定暂存记录(stash@{n}为记录编号,从0开始)
git stash apply stash@{0}
八、操作流程示例(日常开发)
- 克隆仓库:
git clone <远程地址> - 创建新分支开发:
git checkout -b feature/new功能 - 开发中定期提交:
git add .→git commit -m "xxx" - 开发完成后拉取远程最新代码:
git pull origin main(解决冲突) - 推送本地分支到远程:
git push -u origin feature/new功能 - (可选)合并到主分支:切换到 main →
git merge feature/new功能→git push
