Git
分布式版本控制系统 —— 现代软件开发的基石
简介
Git 是一个分布式版本控制系统,由 Linus Torvalds(Linux 内核创始人)于 2005 年创建,用于管理 Linux 内核的源代码开发。
Git 与集中式版本控制的区别
| 特性 | Git(分布式) | SVN(集中式) |
|---|---|---|
| 仓库存储 | 每个开发者本地有完整仓库 | 只有中央服务器有完整仓库 |
| 离线工作 | 完全支持 | 依赖网络连接 |
| 分支操作 | 轻量、快速、本地完成 | 需要与服务器交互 |
| 性能 | 大部分操作在本地,极快 | 依赖网络延迟 |
核心概念
工作区(Working Directory)
↓ git add
暂存区(Staging Area / Index)
↓ git commit
本地仓库(Local Repository)
↓ git push
远程仓库(Remote Repository)- 工作区:你实际编辑代码的目录
- 暂存区:临时存放你准备提交的修改
- 本地仓库:Git 保存版本历史的地方(
.git目录) - 远程仓库:托管在服务器上的仓库副本
Git 客户端
命令行客户端
Git 官方提供命令行工具,是所有 Git 操作的基础。
Windows:https://git-scm.com/download/win
安装时推荐选项:
- 使用 Git Bash(附带 Unix 工具)
- 使用 OpenSSH 作为 SSH 客户端
- 行结束符选择 Checkout as-is, commit Unix-style LF
- 启用 Git Credential Manager(凭证管理)
macOS:
bash
# 方式一:通过 Homebrew
brew install git
# 方式二:通过 Xcode Command Line Tools
xcode-select --installLinux:
bash
# Ubuntu/Debian
sudo apt install git
# CentOS/RHEL
sudo yum install git
# Fedora
sudo dnf install git全局配置
安装后先设置用户名和邮箱(提交记录会用到):
bash
git config --global user.name "Your Name"
git config --global user.email "your@email.com"其他推荐配置:
bash
# 设置默认分支名为 main(替代 master)
git config --global init.defaultBranch main
# 设置默认编辑器
git config --global core.editor "vim"
# 设置别名(简化常用命令)
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.lg "log --oneline --graph --all"
# 设置差异工具
git config --global diff.tool vscode
git config --global merge.tool vscode
# 启用颜色输出
git config --global color.ui auto查看配置:
bash
# 查看所有配置
git config --list
# 查看全局配置
git config --global --list
# 查看特定配置
git config user.name可视化客户端
桌面版客户端
| 客户端 | 平台 | 说明 |
|---|---|---|
| GitHub Desktop | Win / macOS | GitHub 官方出品,简洁易用 |
| Sourcetree | Win / macOS | Atlassian 出品,功能强大 |
| GitKraken | Win / macOS / Linux | 界面最精美,支持多平台 |
| TortoiseGit | Windows | 集成到资源管理器右键菜单 |
| Fork | Win / macOS | 轻量快速,交互优雅 |
IDE 内置 Git 工具
- VSCode — 内置源码管理面板,支持 diff、提交、推送、分支切换
- IntelliJ IDEA — 内置 Git 集成,支持图形化分支管理、可视化冲突解决
- Visual Studio — 内置 Git Changes 面板,支持 PR 管理
终端增强
- Oh My Zsh 的 Git 插件 — 提供丰富的快捷别名(
gst=git status,gco=git checkout等) - diff-so-fancy — Git diff 输出美化
- tig — 终端交互式 Git 浏览器
Git 服务商
公有云服务
| 服务商 | 免费限制 | 特点 |
|---|---|---|
| GitHub | 无限私有仓库,免费 CI/CD | 全球最大,社区活跃,Actions CI/CD,Pages |
| GitLab | 无限私有仓库,400 CI/CD 分钟/月 | DevOps 平台,内置 CI/CD,自托管方案 |
| Gitee(码云) | 私有仓库 5 人团队免费 | 国内加速快,Gitee Pages,中文社区 |
| Bitbucket | 5 人以下免费 | Atlassian 出品,与 Jira 深度集成 |
| Coding | 5 人以下免费 | 腾讯云出品,内置 DevOps,国内加速 |
| 云效(Codeup) | 私有仓库免费,5 人以下 | 阿里云出品,与云效 DevOps 流水线深度集成 |
| Gitea | 完全免费 | 开源、轻量、可自托管 |
镜像加速
国内访问 GitHub 慢时可使用镜像:
或在 Git 中设置代理:
bash
# HTTP 代理
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
# SOCKS5 代理
git config --global http.proxy socks5://127.0.0.1:7890
# 取消代理
git config --global --unset http.proxy
git config --global --unset https.proxy搭建 Git 服务器
方式一:使用 Git 原生协议(轻量)
适用于小团队,基于 SSH 协议,无需额外服务端软件。
bash
# 在服务器上创建裸仓库
ssh user@server
sudo mkdir -p /opt/git/project.git
cd /opt/git/project.git
git init --bare
# 在客户端克隆
git clone ssh://user@server:/opt/git/project.git
# 或使用简写
git clone user@server:/opt/git/project.git权限控制:通过 Linux 系统用户和 SSH 公钥管理(~/.ssh/authorized_keys)。
方式二:Gitea(推荐)
Gitea 是一个用 Go 语言编写的轻量级 Git 服务,资源占用极小,适合个人或小团队。
安装步骤:
bash
# 1. 下载二进制文件
wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/1.22/gitea-1.22-linux-amd64
chmod +x /usr/local/bin/gitea
# 2. 创建运行用户
sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group gitea
# 3. 创建目录结构
sudo mkdir -p /var/lib/gitea/{custom,data,log}
sudo chown -R gitea:gitea /var/lib/gitea
sudo chmod -R 750 /var/lib/gitea
# 4. 启动
sudo -u gitea /usr/local/bin/gitea web或者使用 Docker 一键部署:
bash
docker run -d \
--name=gitea \
-p 3000:3000 \
-p 22:22 \
-v /path/data:/data \
gitea/gitea:latest启动后访问 http://your-server:3000,按照引导完成初始配置即可。
方式三:GitLab(企业级)
GitLab 功能最完整,包含 CI/CD、容器镜像仓库、项目管理等。
bash
# Ubuntu 一键安装(推荐 4GB+ 内存)
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix # 邮件服务器
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash
sudo EXTERNAL_URL="https://gitlab.your-domain.com" apt-get install gitlab-eeDocker 部署:
bash
docker run -d \
--name gitlab \
-p 443:443 -p 80:80 -p 22:22 \
-v /srv/gitlab/config:/etc/gitlab \
-v /srv/gitlab/logs:/var/log/gitlab \
-v /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ee:latest方式四:Hugo / Express 自定义服务器
对于有开发能力的团队,可以使用 go-git(Go)或 nodegit(Node.js)等库自行封装 Git 服务器逻辑。
Node.js 示例(使用 isomorphic-git):
javascript
// 一个极简的自定义 Git 服务器入口框架
const express = require('express')
const { clone, push, listFiles } = require('isomorphic-git')
const fs = require('fs')
const app = express()
app.post('/clone', async (req, res) => {
await clone({
fs,
dir: `/repos/${req.body.repoName}`,
url: req.body.url,
singleBranch: true,
depth: 1
})
res.json({ message: 'clone success' })
})
app.listen(3000)Git 工作流程
单人开发
main ── feat1 ── feat2 ── feat3最简单的流程,直接在主干分支上开发和提交。
团队协作(Git Flow)
main ──────────────────── 发布版
│
└── develop ────────────────── 开发主线
│
├── feature/login 用户登录功能
├── feature/register 用户注册功能
└── release/1.0 发布准备
master ── 随时可部署的稳定版本
develop ── 开发主线
feature/* ── 功能特性分支
release/* ── 发布准备分支
hotfix/* ── 紧急修复分支简易团队流程(GitHub Flow)
main ──── 始终可部署
│
├── feat-a → Pull Request → main
├── feat-b → Pull Request → main
└── fix-c → Pull Request → main原则:
main分支始终是可部署的- 从
main创建特性分支 - 在特性分支上开发并提交
- 创建 Pull Request 进行代码审查
- 合并回
main
GitLab Flow
main ── 开发
└── pre-production ── 预发布
└── production ── 生产环境常用命令
仓库操作
bash
# 初始化新仓库
git init
# 克隆远程仓库
git clone https://github.com/user/repo.git
git clone git@github.com:user/repo.git
# 克隆指定分支
git clone -b develop https://github.com/user/repo.git
# 克隆时指定深度(加速大仓库克隆)
git clone --depth 1 https://github.com/user/repo.git基础操作
bash
# 查看状态
git status
git status -s # 简短输出
# 将文件加入暂存区
git add filename # 添加指定文件
git add . # 添加所有更改
git add -p # 交互式分块添加
# 提交
git commit -m "feat: 添加用户登录功能"
git commit -am "fix: 修复空指针异常" # 跳过 git add(仅限已跟踪文件)
git commit --amend # 修正上一次提交
git commit --amend --no-edit # 不动提交信息,只合并文件
# 查看提交历史
git log
git log --oneline # 简洁模式
git log --oneline --graph # 图形化
git log -n 5 # 最近 5 条
git log --author="name" # 按作者过滤
git log --since="2024-01-01" # 按时间过滤分支管理
bash
# 查看分支
git branch # 本地分支
git branch -r # 远程分支
git branch -a # 所有分支
# 创建和切换
git branch feature # 创建分支
git checkout feature # 切换分支
git checkout -b feature # 创建并切换
git switch feature # 切换分支(新版 Git)
git switch -c feature # 创建并切换(新版 Git)
# 合并
git merge feature # 将 feature 合并到当前分支
git merge --no-ff feature # 禁止快进合并,保留分支历史
# 删除分支
git branch -d feature # 删除本地分支
git branch -D feature # 强制删除
git push origin --delete feature # 删除远程分支
# 重命名分支
git branch -m old-name new-name远程操作
bash
# 查看远程仓库
git remote -v
# 添加远程仓库
git remote add origin https://github.com/user/repo.git
# 推送
git push origin main
git push -u origin feature # 设置上游分支(首次推送)
git push --all # 推送所有分支
git push --tags # 推送标签
# 拉取
git pull # fetch + merge
git pull --rebase # fetch + rebase
git fetch # 拉取但不合并
git fetch -p # 拉取并清理已删除的远程分支
# 设置默认推送分支
git push -u origin main查看与比较
bash
# 查看工作区 vs 暂存区的差异
git diff
# 查看暂存区 vs 本地仓库的差异
git diff --staged
# 查看两个分支的差异
git diff main..feature
# 查看某个文件的修改历史
git log -p filename
# 查看某次提交的具体修改
git show commit_hash
# 查看某个文件的每一行最后是谁修改的
git blame filename撤销与回退
bash
# 撤销工作区的修改(恢复到暂存区或 HEAD 的状态)
git checkout -- filename
git restore filename # 新版 Git 推荐
# 将文件从暂存区移回工作区
git reset HEAD filename
git restore --staged filename # 新版 Git 推荐
# 撤销最近一次提交(保留修改到工作区)
git reset --soft HEAD~1
# 撤销最近一次提交(保留修改到暂存区)
git reset --mixed HEAD~1
# 撤销最近一次提交(丢弃修改,危险)
git reset --hard HEAD~1
# 推送到远程后想回退
git reset --hard HEAD~1
git push --force # 慎用,会覆盖远程历史
# 更安全的远程回退:创建一个反向提交
git revert HEAD
git revert commit_hash标签管理
bash
# 创建标签
git tag v1.0.0
git tag -a v1.0.0 -m "发布 v1.0.0 版本"
# 查看标签
git tag
git tag -l "v1.0.*"
# 推送标签
git push origin v1.0.0
git push --tags
# 删除标签
git tag -d v1.0.0
git push origin --delete v1.0.0储藏(Stash)
bash
# 临时保存工作区修改
git stash
git stash save "描述信息"
# 查看储藏列表
git stash list
# 恢复最近的储藏
git stash pop
# 恢复但不删除
git stash apply
# 恢复指定的储藏
git stash apply stash@{2}
# 删除储藏
git stash drop stash@{0}
git stash clear # 清除所有储藏子模块
bash
# 添加子模块
git submodule add https://github.com/user/lib.git libs/lib
# 初始化并更新子模块
git clone --recursive https://github.com/user/repo.git
git submodule update --init --recursive
# 更新子模块到最新
git submodule update --remote
# 同步子模块地址
git submodule sync团队协作中的 Git
分支命名规范
feature/xxx 功能开发
feature/user-login
feature/order-list
bugfix/xxx 缺陷修复
bugfix/null-pointer
hotfix/xxx 紧急修复
hotfix/security-patch
release/xxx 发布准备
release/v1.2.0
chore/xxx 工程化/配置
chore/ci-pipeline提交信息规范(Conventional Commits)
<type>(<scope>): <subject>
<body>
<footer>| type | 说明 |
|---|---|
feat | 新功能 |
fix | 修复 bug |
docs | 文档更新 |
style | 代码格式调整(不影响逻辑) |
refactor | 重构(既不修复 bug 也不添加功能) |
perf | 性能优化 |
test | 测试相关 |
chore | 构建过程或辅助工具的变动 |
示例:
feat(auth): 添加微信扫码登录功能
- 集成微信 OAuth 2.0
- 添加扫码登录按钮
- 处理回调并绑定用户
Closes #123.gitignore 文件
gitignore
# IDE
.idea/
.vscode/
*.iml
# 构建产物
target/
build/
dist/
out/
# 依赖
node_modules/
vendor/
libs/
# 环境配置
.env
.env.local
*.env.local
# 操作系统
.DS_Store
Thumbs.db
# 日志
*.log
logs/
# 临时文件
*.tmp
*.swpGitee / GitHub 与 CI/CD 集成
yaml
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: '21'
- name: Build
run: mvn clean package
- name: Deploy
if: github.ref == 'refs/heads/main'
run: scp target/app.jar user@server:/deploy/冲突处理
冲突产生的原因:两个分支修改了同一文件的相同位置。
产生冲突的场景
1. 两个分支同时修改了同一行
2. 一个分支删除了文件,另一个分支修改了该文件
3. 一个分支修改了文件名,另一个分支修改了文件内容解决冲突步骤
bash
# 1. 切换到目标分支
git checkout main
# 2. 合并特性分支
git merge feature/login
# 输出示例:
# Auto-merging src/UserService.java
# CONFLICT (content): Merge conflict in src/UserService.java
# Automatic merge failed; fix conflicts and then commit the result.3. 查看冲突文件
bash
git status
# both modified: src/UserService.java4. 编辑冲突文件
冲突标记格式:
java
public class UserService {
<<<<<<< HEAD
public void login(String username, String password) {
// 老的登录逻辑
=======
public void login(String username, String password, String captcha) {
// 新的登录逻辑,增加了验证码
>>>>>>> feature/login
}
}解决方式:
- 保留当前分支:删除
=======到>>>>>>>之间的内容 - 保留传入分支:删除
<<<<<<<到=======之间的内容 - 合并两者:手动编辑保留两边的逻辑
解决后:
java
public class UserService {
public void login(String username, String password, String captcha) {
// 合并后的登录逻辑
}
}5. 标记为已解决并提交
bash
git add src/UserService.java
git commit -m "fix: 合并冲突 - 更新登录接口增加验证码参数"使用可视化合并工具
bash
# 启动合并工具
git mergetool
# 常用合并工具
git config merge.tool vscode
git config merge.tool p4merge # Perforce 合并工具预防冲突的策略
- 频繁同步:勤
git pull,减少分支间的差距 - 单一职责:一个分支只做一件事,减少修改范围
- 解耦:模块化设计,减少多人同时修改同一文件
- 小粒度提交:每次提交只包含相关的修改,描述清晰
- 使用 Pull Request:合并前进行代码审查,尽早发现冲突
- 采用 Rebase 策略:保持线性历史,减少无意义的分支
bash
# 推荐:合并前先 rebase 到目标分支
git checkout feature
git rebase main
# 解决冲突后
git add <file>
git rebase --continue
# 回到主分支完成合并
git checkout main
git merge featureGit 高级技巧
交互式 Rebase
用于整理提交历史:
bash
# 修改最近 3 次提交
git rebase -i HEAD~3
# 命令选项:
# pick 使用该提交
# reword 修改提交信息
# edit 修改提交内容
# squash 合并到上一个提交
# fixup 合并到上一个提交并丢弃提交信息
# drop 删除该提交bisect(二分查找定位问题)
bash
# 开始查找
git bisect start
# 标记当前版本为坏版本
git bisect bad
# 标记已知的好版本
git bisect good v1.0.0
# Git 会二分切出一个中间版本,测试后标记:
git bisect good # 如果当前版本正常
git bisect bad # 如果当前版本有问题
# 直到定位到第一个出问题的提交
# 结束 bisect
git bisect resetcherry-pick(选择性合并)
bash
# 将某个提交应用到当前分支
git cherry-pick commit_hash
# 连续多个提交
git cherry-pick start_hash..end_hash
# 合并到当前分支但不自动提交
git cherry-pick -n commit_hashreflog(操作日志 - 救援利器)
bash
# 查看所有 Git 操作历史
git reflog
# 找回丢失的提交
git reflog # 找到丢失的 commit_hash
git checkout commit_hash
git branch recover-branch # 从该提交创建分支最佳实践
一天的工作流
bash
# 早上开始工作
git checkout main
git pull # 同步最新代码
git checkout -b feat/xxx # 创建特性分支
# 工作中多次提交
git add . && git commit -m "feat: xxx"
# 推送分支到远程
git push -u origin feat/xxx
# 创建 Pull Request 请求合并
# 晚上下班前
# 确保所有更改已提交并推送
# 清理本地过期分支
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d代码审查清单
- [ ] 分支命名符合规范
- [ ] 提交信息清晰、规范
- [ ] 只包含相关的修改,不混入无关代码
- [ ] 通过了本地测试
- [ ] CI 构建通过
- [ ] 解决了所有冲突
- [ ] 必要的新增了测试用例
附:Git 速查表
bash
# ┌──────────────────────────────────────────────┐
# │ Git 命令速查表 │
# ├──────────────────────────────────────────────┤
# │ 创建 │
# │ git init 初始化仓库 │
# │ git clone 克隆远程仓库 │
# ├──────────────────────────────────────────────┤
# │ 本地操作 │
# │ git add 暂存文件 │
# │ git commit 提交 │
# │ git diff 查看差异 │
# │ git log 查看历史 │
# ├──────────────────────────────────────────────┤
# │ 分支操作 │
# │ git branch 管理分支 │
# │ git checkout 切换分支 │
# │ git merge 合并分支 │
# │ git rebase 变基 │
# ├──────────────────────────────────────────────┤
# │ 远程操作 │
# │ git push 推送 │
# │ git pull 拉取 │
# │ git fetch 获取 │
# │ git remote 管理远程仓库 │
# ├──────────────────────────────────────────────┤
# │ 撤销 │
# │ git reset 回退 │
# │ git revert 反向提交 │
# │ git stash 储藏 │
# │ git restore 恢复文件 │
# └──────────────────────────────────────────────┘