瑞克
Published on 2026-07-15 / 0 Visits
0
0

Git与GitHub

Git与GitHub——代码的"时光机"与"协作平台"

写在前面:想象你写一篇3万字的毕业论文,每改一版都要另存为"论文_v1""论文_v2_最终版""论文_v2_最终版_真的最终版"...。Git就是帮你彻底告别这种噩梦的工具——它记录每一次改动,随时可以"时光倒流"。GitHub则把Git搬到了云端,让全世界的人一起协作。本章我们从零开始,把Git和GitHub玩明白!


1 版本控制的概念——为什么需要"后悔药"

生活类比

版本控制就像手机相册的"编辑历史":你对照片做了裁剪、调色、加滤镜,每一步都可以回退到之前的状态,而不用重新拍一张。

没有版本控制的痛苦

场景结果
删了一段代码,后来发现还需要找不回来了
两人同时改同一个文件互相覆盖,不知道谁改了什么
想看看上周的代码长什么样没法对比,只能凭记忆
上线后发现bug不知道是哪次提交引入的

SVN vs Git 对比

特性SVN(集中式)Git(分布式)
架构中央服务器存储所有版本每个人本地都有完整仓库
离线工作无法提交可以离线提交,之后再推送
分支管理分支=目录拷贝,笨重分支=指针移动,极轻量
速度每次操作都要连服务器大多数操作在本地完成,极快
适用场景小团队、老项目几乎所有现代项目

互动提问:为什么Git是"分布式"的?好处是什么?

点击查看答案 每个开发者的电脑上都有完整的仓库副本(包含所有历史),即使服务器宕机,任何一个人的本地仓库都可以恢复整个项目。这就是分布式的安全感。

2 Git安装——各发行版安装方式

CentOS / RHEL

# 使用yum安装
sudo yum install -y git

# 验证安装
git --version

Ubuntu / Debian

# 先更新软件源
sudo apt update
sudo apt install -y git

# 验证
git --version

从源码编译(获取最新版本)

# 1. 安装编译依赖
sudo yum install -y curl-devel expat-devel gettext-devel \
    openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker

# 2. 下载源码
cd /usr/src
sudo wget https://github.com/git/git/archive/v2.43.0.tar.gz -O git.tar.gz
sudo tar xzf git.tar.gz
cd git-*

# 3. 编译安装
sudo make prefix=/usr/local all
sudo make prefix=/usr/local install

# 4. 验证
git --version

3 Git配置——告诉Git"你是谁"

# 全局配置(对所有仓库生效)
git config --global user.name "张三"
git config --global user.email "zhangsan@example.com"

# 查看配置
git config --list
git config user.name

# 配置默认编辑器
git config --global core.editor vim

# 配置颜色输出
git config --global color.ui auto

# 配置别名(偷懒必备)
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 st       # 等价于 git status
git co dev   # 等价于 git checkout dev
git lg       # 漂亮的图形化日志

为什么要配置user.name和email?
Git的每次commit都会记录作者信息。如果不配置,Git会拒绝提交——就像一个匿名信没有署名,无法追溯。


##4 工作区三阶段——Git的核心思想

生活类比

想象你在做一份PPT作业:

  • 工作区(Working Directory)= 你桌面上正在编辑的PPT文件
  • 暂存区(Staging Area / Index)= 你把改好的几页拖到"待提交"文件夹
  • 本地仓库(Repository)= 你点了"保存版本",这版被永久记录
    工作区              暂存区              本地仓库
  (Working)    →    (Staging)    →    (Repository)
   编辑文件     add   准备提交    commit   永久记录
   
   ← reset               ← checkout
   撤销修改               还原文件

三个区域之间的流转:

操作方向说明
git add工作区 → 暂存区把修改标记为"准备提交"
git commit暂存区 → 仓库把暂存的内容永久保存
git reset仓库 → 暂存区撤销暂存(不影响工作区)
git checkout仓库 → 工作区用仓库版本覆盖工作区

5 基本操作——Git入门六板斧

5.1 git init——创建仓库

# 创建新项目
mkdir my-project && cd my-project
git init
# 输出:Initialized empty Git repository in /path/to/my-project/.git/

# 此时会生成一个隐藏的 .git 目录,存放所有版本数据
ls -la .git/

5.2 git add——添加到暂存区

# 添加单个文件
git add index.html

# 添加多个文件
git add style.css script.js

# 添加所有改动(最常用)
git add .

# 添加所有改动但排除已删除的文件
git add -u

5.3 git commit——提交到仓库

# 标准提交
git commit -m "feat: 添加用户登录功能"

# 提交并自动add已跟踪的文件
git commit -am "fix: 修复导航栏样式问题"

# 修改上一次提交的消息
git commit --amend -m "feat: 添加用户登录功能(含表单验证)"

提交消息规范(推荐Conventional Commits):

feat:     新功能
fix:      修复bug
docs:     文档更新
style:    代码格式(不影响逻辑)
refactor: 重构
test:     添加测试
chore:    构建/工具变动

5.4 git status——查看状态

git status
# 输出示例:
# On branch main
# Changes to be committed:
#   (use "git restore --staged <file>..." to unstage)
#         modified:   index.html
#
# Changes not staged for commit:
#         modified:   style.css
#
# Untracked files:
#         new_feature.js

# 简洁模式
git status -s
# 输出:
# M  index.html      ← 已暂存(绿色M)
#  M style.css       ← 未暂存(红色M)
# ?? new_feature.js  ← 未跟踪

5.5 git log——查看历史

# 标准日志
git log

# 单行简洁模式(最推荐)
git log --oneline
# 输出:
# a3f2b1c feat: 添加登录功能
# 9e8d7c6 fix: 修复首页bug
# 1a2b3c4 init: 项目初始化

# 图形化分支日志
git log --oneline --graph --all

# 查看最近3次提交
git log -3

# 查看某个文件的历史
git log --follow -p index.html

# 查看某个作者的提交
git log --author="张三"

# 查看某天的提交
git log --since="2024-01-01" --until="2024-01-31"

# 查看某次提交改了什么
git show a3f2b1c

5.6 git diff——查看差异

# 工作区 vs 暂存区(还没add的修改)
git diff

# 暂存区 vs 仓库(已add但没commit的修改)
git diff --staged
# 或
git diff --cached

# 两个提交之间的差异
git diff abc123 def456

# 两个分支之间的差异
git diff main feature/login

5.7 git reset——撤销与回退

# 撤销暂存(文件内容不变)
git reset HEAD style.css
# 等价于
git restore --staged style.css

# 回退到某次提交(保留修改在工作区)—— 最常用
git reset --mixed abc123

# 回退到某次提交(保留修改在暂存区)
git reset --soft abc123

# 彻底回退到某次提交(丢弃所有修改)—— 慎用!
git reset --hard abc123

# 回退上一个提交
git reset --hard HEAD~1

# 只撤销某个文件的某次修改
git checkout abc123 -- filename

互动提问git reset --hardgit reset --soft 的区别是什么?

点击查看答案 `--hard`:彻底回退,工作区和暂存区都恢复到目标提交的状态,未提交的修改全部丢失。`--soft`:只移动HEAD指针,修改保留在暂存区,可以重新commit。日常使用中 `--mixed`(默认)最安全。

6 分支——平行宇宙的魔法

生活类比

分支就像游戏的"存档点":你可以在主线剧情之外开一个"支线任务"(新分支),做完了可以合并回主线,也可以直接放弃支线。

6.1 分支基础操作

# 查看所有分支(当前分支带*号)
git branch
# 输出:
#   develop
# * main
#   feature/login

# 创建新分支
git branch feature/login

# 切换到新分支
git checkout feature/login
# 或更简洁的一步到位:
git checkout -b feature/login

# 新版Git推荐用switch
git switch -c feature/login

# 删除分支(必须先切到其他分支)
git branch -d feature/login     # 安全删除(已合并的才能删)
git branch -D feature/login     # 强制删除(未合并也能删)

# 重命名当前分支
git branch -m new-name

6.2 分支合并(merge)

# 场景:feature/login 开发完了,合并到 main

# 1. 切回主线
git checkout main

# 2. 合并
git merge feature/login
# 输出:
# Updating a3f2b1c..b4c3d2e
# Fast-forward
#  login.html | 50 ++++++++++
#  1 file changed, 50 insertions(+)

# 3. 删除已合并的分支
git branch -d feature/login

# 合并时保留分支历史(生成合并提交)
git merge --no-ff feature/login -m "merge: 合并登录功能分支"

6.3 变基(rebase)

# rebase把当前分支的提交"搬"到目标分支的最新提交之后
# 让提交历史更线性、更干净

git checkout feature/login
git rebase main

# 如果rebase过程中遇到冲突
# 1. 手动解决冲突
# 2. git add 解决后的文件
# 3. git rebase --continue

# 放弃rebase
git rebase --abort

merge vs rebase 如何选择?

方式优点缺点适用场景
merge保留完整历史历史可能很乱公共分支合并
rebase历史清晰线性改写提交历史个人分支整理

黄金法则:不要对已经推送到远程的公共分支执行rebase!

6.4 冲突解决

# 当两人修改了同一文件的同一位置时,Git会报冲突
# 冲突文件内容会变成:

# <<<<<<< HEAD
# 这是你修改的内容
# =======
# 这是别人修改的内容
# >>>>>>> feature/other-branch

# 解决步骤:
# 1. 手动编辑文件,删除冲突标记,保留正确内容
vim conflict_file.txt

# 2. 标记为已解决
git add conflict_file.txt

# 3. 提交合并结果
git commit -m "merge: 解决登录模块冲突"

实战冲突解决示例:

# 模拟冲突场景
git checkout -b branch-a
echo "张三的代码" > code.txt
git add code.txt && git commit -m "张三修改"

git checkout main
git checkout -b branch-b
echo "李四的代码" > code.txt
git add code.txt && git commit -m "李四修改"

git checkout main
git merge branch-a    # 成功
git merge branch-b    # 冲突!

# 编辑code.txt,选择保留哪份或合并两份
vim code.txt
git add code.txt
git commit -m "merge: 合并张三和李四的代码"

7 远程仓库——连接世界

生活类比

本地仓库是你的笔记本,远程仓库就是云盘——你把笔记同步到云盘,别人也能看到和协作。

7.1 基本远程操作

# 查看远程仓库
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 clone https://github.com/user/repo.git
cd repo

# 克隆到指定目录
git clone https://github.com/user/repo.git my-project

# 只克隆最近1次提交(加快速度)
git clone --depth 1 https://github.com/user/repo.git

7.2 push / pull / fetch

# push:推送本地提交到远程
git push origin main
git push origin feature/login

# 第一次推送时设置上游分支
git push -u origin main

# pull:拉取远程变更并合并(= fetch + merge)
git pull origin main

# fetch:只拉取远程变更,不自动合并(更安全)
git fetch origin
git log main..origin/main   # 查看远程比本地多了什么
git merge origin/main        # 确认后再合并

# 拉取所有分支
git fetch --all

日常工作流:

# 每天开工第一件事:拉取最新代码
git pull origin main

# 干活...编辑文件...
git add .
git commit -m "feat: 完成XX功能"
git push origin main

# 下班前确认没有遗漏
git status
git log --oneline -5

8 GitHub使用——全球最大的代码托管平台

8.1 注册与配置

  1. 访问 https://github.com 注册账号
  2. 配置SSH密钥(免密码推送)
# 生成SSH密钥对
ssh-keygen -t ed25519 -C "your_email@example.com"

# 查看公钥
cat ~/.ssh/id_ed25519.pub

# 复制公钥内容,添加到 GitHub → Settings → SSH and GPG keys

8.2 Fork与Pull Request

Fork工作流(参与开源项目的标准流程):

1. 在GitHub上点击项目的 "Fork" 按钮 → 复制一份到你自己的账号下
2. git clone 你fork后的仓库到本地
3. 创建分支,修改代码
4. git push 到你的fork仓库
5. 在GitHub上发起 Pull Request (PR) → 请求原项目合并你的改动
6. 项目维护者审核代码 → 合并
# 具体操作
git clone git@github.com:你的用户名/project.git
cd project

# 添加上游仓库(方便同步原项目的更新)
git remote add upstream https://github.com/原作者/project.git

# 同步上游更新
git fetch upstream
git merge upstream/main

# 创建功能分支
git checkout -b fix/typo-in-readme
# ... 修改文件 ...
git add . && git commit -m "docs: 修复README中的拼写错误"
git push origin fix/typo-in-readme
# 然后到GitHub网页上创建Pull Request

8.3 Issues(问题追踪)

GitHub Issues 是项目的问题追踪系统,可以用来:

  • 报告bug
  • 提出功能建议
  • 讨论技术方案
# 一个好的Issue模板
## Bug描述
简要说明问题现象

## 复现步骤
1. 第一步...
2. 第二步...
3. 出现错误

## 期望行为
应该怎样工作

## 环境信息
- OS: Ubuntu 22.04
- 版本: v1.2.3

9 GitHub Pages——免费建站

GitHub Pages可以把仓库里的HTML/CSS/JS文件直接发布为网站。

# 1. 创建仓库:用户名.github.io
# 2. 上传index.html
# 3. 访问 https://用户名.github.io

# 或者用任意仓库的gh-pages分支
git checkout -b gh-pages
# 添加HTML文件
git add . && git commit -m "init: GitHub Pages"
git push origin gh-pages
# 在仓库Settings → Pages中选择gh-pages分支发布

适合搭建的内容:

  • 个人博客(配合Jekyll/Hugo)
  • 项目文档
  • 个人简历页
  • 课程作业展示

10 .gitignore——告诉Git"别跟踪这些文件"

# .gitignore 文件示例

# 忽略编译产物
*.o
*.class
*.pyc
__pycache__/
dist/
build/

# 忽略IDE配置
.vscode/
.idea/
*.swp

# 忽略系统文件
.DS_Store
Thumbs.db

# 忽略敏感信息(非常重要!)
.env
*.pem
*.key
secrets/

# 忽略日志
*.log
logs/

# 忽略依赖目录
node_modules/
vendor/

常见规则:

*.log         # 忽略所有.log文件
build/        # 忽略build目录
doc/*.txt     # 忽略doc下的.txt(不含子目录)
doc/**/*.txt  # 忽略doc及其子目录下的所有.txt
!important.log  # 不忽略important.log(即使前面有*.log)

如果文件已经被跟踪了,如何从Git中移除但保留本地文件?

git rm --cached filename
git rm -r --cached directory/
git commit -m "chore: 移除不应跟踪的文件"

11 tag——给版本打标签

# 创建轻量标签
git tag v1.0.0

# 创建附注标签(推荐,包含作者和说明)
git tag -a v1.0.0 -m "Release v1.0.0: 首个正式版"

# 给历史提交打标签
git tag -a v0.9.0 abc123 -m "Beta版本"

# 查看所有标签
git tag
git tag -l "v1.*"    # 通配查找

# 查看标签详情
git show v1.0.0

# 推送标签到远程
git push origin v1.0.0
git push origin --tags    # 推送所有标签

# 删除标签
git tag -d v1.0.0                     # 删除本地
git push origin --delete v1.0.0       # 删除远程

12 cherry-pick——精挑细选某个提交

# 场景:main分支有个bugfix,你也想在你的分支上用
# 不用全部merge,只需cherry-pick那一个提交

git checkout feature/login
git cherry-pick abc123    # 把abc123这个提交"摘"过来

# 一次摘多个
git cherry-pick abc123 def456 ghi789

# 遇到冲突时
# 解决冲突后:
git cherry-pick --continue
# 或放弃:
git cherry-pick --abort

13 stash——临时保存工作现场

生活类比

stash就像"存档":你正在打Boss(写代码),突然要去做另一件事,赶紧存个档,做完回来读档继续。

# 保存当前未提交的修改
git stash
git stash save "正在做的登录功能,临时切换修bug"

# 查看已保存的stash列表
git stash list
# 输出:
# stash@{0}: On feature/login: 正在做的登录功能
# stash@{1}: On main: 临时修改

# 恢复最近一次stash
git stash pop             # 恢复并删除该stash
git stash apply           # 恢复但保留stash

# 恢复指定的stash
git stash pop stash@{1}

# 删除某个stash
git stash drop stash@{1}

# 清空所有stash
git stash clear

典型使用场景:

# 你正在feature分支开发,突然要切到main修紧急bug
git stash                    # 先存档
git checkout main            # 切分支
# ...修bug、提交、推送...
git checkout feature/login   # 切回来
git stash pop                # 读档继续

14 git reflog——救命命令

生活类比

reflog是Git的"黑匣子":即使你 git reset --hard 删掉了提交,reflog依然记录了所有操作。它是你最后的救命稻草。

# 查看所有操作历史(包括已"删除"的提交)
git reflog
# 输出:
# a3f2b1c HEAD@{0}: commit: feat: 添加新功能
# 9e8d7c6 HEAD@{1}: reset: moving to HEAD~3
# b4c3d2e HEAD@{2}: commit: fix: 重要修复
# c5d4e3f HEAD@{3}: commit: docs: 更新文档

# 场景:不小心 git reset --hard 丢掉了3个提交
# 从reflog中找到丢失的提交hash,然后恢复:
git reset --hard b4c3d2e    # 恢复到"重要修复"那个状态

# 也可以用cherry-pick恢复单个提交
git cherry-pick b4c3d2e

互动提问:reflog和log有什么区别?

点击查看答案 `git log` 只显示当前分支的提交历史(已删除的看不到);`git reflog` 记录HEAD指针的所有移动(包括reset、rebase、checkout等操作),是本地操作日志。reflog默认保留90天。

15 Jenkins简介——自动化部署的"机器人"

什么是Jenkins?

Jenkins是一个开源的**持续集成/持续部署(CI/CD)**工具。简单来说,它就是一个"机器人":

  • 你推送代码 → Jenkins自动运行测试
  • 测试通过 → Jenkins自动打包部署到服务器
  • 测试失败 → Jenkins发邮件通知你

安装Jenkins

# CentOS安装
sudo wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io-2023.key
sudo yum install -y jenkins java-17-openjdk

# 启动服务
sudo systemctl start jenkins
sudo systemctl enable jenkins

# 查看初始密码
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

# 访问 http://服务器IP:8080 完成初始化

Pipeline基础(Jenkinsfile)

// Jenkinsfile —— 定义CI/CD流水线
pipeline {
    agent any

    environment {
        APP_NAME = 'my-web-app'
        DEPLOY_DIR = '/var/www/html'
    }

    stages {
        stage('拉取代码') {
            steps {
                git branch: 'main',
                    url: 'https://github.com/user/repo.git'
            }
        }

        stage('安装依赖') {
            steps {
                sh 'npm install'
            }
        }

        stage('运行测试') {
            steps {
                sh 'npm test'
            }
        }

        stage('构建') {
            steps {
                sh 'npm run build'
            }
        }

        stage('部署') {
            steps {
                sh "cp -r dist/* ${DEPLOY_DIR}/"
                sh 'systemctl restart nginx'
            }
        }
    }

    post {
        success {
            echo "部署成功!"
            // 可以发送通知
        }
        failure {
            echo "构建失败,请检查代码!"
        }
    }
}

Jenkins工作流程图:

开发者git push → GitHub Webhook触发 → Jenkins拉取代码
    → 安装依赖 → 运行测试 → 构建 → 部署到服务器
    → 成功:通知团队
    → 失败:通知开发者修复

16 Git实战工作流总结

个人项目工作流

# 1. 初始化
mkdir project && cd project
git init
echo "# My Project" > README.md
git add . && git commit -m "init: 项目初始化"

# 2. 开发新功能
git checkout -b feature/xxx
# ...编码...
git add . && git commit -m "feat: 完成xxx"
git checkout main
git merge feature/xxx
git tag v1.0.0

# 3. 推送到远程
git remote add origin git@github.com:user/repo.git
git push -u origin main
git push --tags

团队协作工作流

# 每天开工
git pull origin main
git checkout -b feature/my-task

# 开发中(定期暂存)
git add .
git commit -m "feat: 进度更新"

# 提交前同步主线
git fetch origin
git rebase origin/main
# 解决冲突(如果有)

# 推送并创建PR
git push -u origin feature/my-task
# 在GitHub上创建Pull Request

# PR合并后清理
git checkout main
git pull origin main
git branch -d feature/my-task

运维常用命令精选

日常高频命令

git status -s                         # 快速查看状态
git add . && git commit -m "msg"      # 快速提交
git log --oneline -10                 # 查看最近10次提交
git diff --stat                       # 查看修改了哪些文件
git pull --rebase origin main         # 拉取并变基(保持历史整洁)

分支管理

git branch -vv                        # 查看分支跟踪关系
git branch --merged                   # 查看已合并的分支(可安全删除)
git branch -d $(git branch --merged | grep -v main)  # 批量删除已合并分支

排查与恢复

git reflog                            # 查看所有操作记录(救命用)
git blame filename                    # 查看每行是谁改的
git bisect start                      # 二分法查找引入bug的提交
git stash list                        # 查看暂存的修改

远程同步

git remote -v                         # 查看远程仓库地址
git fetch --all --prune               # 拉取所有远程并清理已删除的分支
git push origin --tags                # 推送所有标签

趣味命令专区

# 1. 查看你的Git统计信息
git log --author="你的名字" --oneline | wc -l   # 你提交了多少次
git log --author="你的名字" --shortstat          # 增删了多少行

# 2. 用ASCII图形看分支历史
git log --oneline --graph --all --decorate

# 3. 查看今天改了什么
git diff --stat HEAD@{0}@{2024-01-01}

# 4. 找出仓库中最大的文件
git rev-list --objects --all | \
    git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
    sort -k3 -n | tail -10

# 5. 生成变更日志
git log --pretty=format:"%h %ad | %s [%an]" --date=short > CHANGELOG.txt

# 6. 一键初始化项目(含.gitignore)
mkdir my-project && cd my-project && \
    git init && \
    echo "node_modules/\n.env\n*.log\ndist/" > .gitignore && \
    echo "# My Project" > README.md && \
    git add . && git commit -m "init: 项目初始化"

# 7. 统计团队贡献
git shortlog -sn --all
# 输出:
#   150  张三
#    89  李四
#    45  王五

# 8. 查看某天的代码改动
git log --since="2024-03-01" --until="2024-03-02" -p --stat

# 9. 有趣的Git Easter Egg
git help everyday    # Git的"日常指南"

本章小结:Git是程序员的"后悔药"和"协作桥梁"。记住三个核心概念:三阶段流转(工作区→暂存区→仓库)、分支管理(创建→开发→合并)、远程同步(push/pull/fetch)。遇到问题别慌,git reflog永远是你的救命稻草。GitHub则让协作跨越了地理限制——Fork、PR、Issues三板斧,让你参与全球开源项目不再是梦。


Comment