Contents

Git命令练习与实战

练习前准备

设置工作环境

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 创建练习目录
mkdir git-practice
cd git-practice

# 查看是否已配置用户信息
git config --global --list | grep user

# 如果未设置,配置用户信息
git config --global user.name "Your Name"
git config --global user.email "your.email@example.com"

基础操作

练习 1:仓库初始化与基本提交

创建项目结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 1. 创建并进入练习目录
mkdir exercise1
cd exercise1

# 2. 初始化仓库
git init

# 3. 创建文件
echo "# 这是一个Git练习项目" > README.md

cat > main.py << EOF
#!/usr/bin/env python3
print("Hello Git")
EOF

echo "测试数据1
测试数据2
测试数据3" > data.txt

分次提交

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 4. 提交README.md
git add README.md
git commit -m "添加README文件"

# 5. 提交main.py
git add main.py
git commit -m "添加主程序文件"

# 查看状态
git status
# 预期:显示data.txt是未跟踪文件

6-7:查看状态和历史

1
2
3
4
5
6
7
8
9
# 6. 查看状态
git status
# 输出应显示:data.txt (untracked)

# 7. 查看提交历史
git log --oneline
# 预期输出类似:
# 2a3b4c5 添加主程序文件
# 1a2b3c4 添加README文件

8-10:修改和提交

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 8. 修改main.py
cat >> main.py << EOF

def add_numbers(a, b):
    return a + b

if __name__ == "__main__":
    result = add_numbers(5, 3)
    print(f"5 + 3 = {result}")
EOF

# 9. 查看差异
git diff
# 显示main.py的修改内容

# 10. 一次性提交所有修改
git add .
git commit -m "为main.py添加add_numbers函数并提交所有文件"

# 验证
git log --oneline --graph
# 应该有3次提交

练习 2:文件管理

1-2:创建文件结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 回到git-practice目录
cd ../

# 1. 创建并进入exercise2
mkdir exercise2
cd exercise2
git init

# 2. 创建文件结构
mkdir src logs temp

echo "print('App started')" > src/app.py
echo "def helper(): pass" > src/utils.py

echo "2024-01-01 INFO: App started" > logs/app.log
echo "2024-01-01 ERROR: Something wrong" > logs/error.log

echo "temporary data" > temp/cache.tmp
echo "[database]
host=localhost
port=5432" > config.ini

3-5:.gitignore 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3. 暂存所有文件
git add .

# 4. 从暂存区移除logs文件(但不删除)
git rm --cached logs/app.log logs/error.log

# 5. 创建.gitignore
cat > .gitignore << EOF
# 忽略所有日志文件
*.log

# 忽略temp目录
temp/

# 忽略临时文件
*.tmp

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

# 验证哪些文件被跟踪
git status
# 预期:logs/下的文件显示为untracked,temp/下的文件完全不显示

6-7:重命名和提交

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 6. 重命名文件
git mv config.ini settings.ini

# 查看状态
git status
# 应该显示:renamed: config.ini -> settings.ini

# 7. 提交
git add .gitignore
git commit -m "初始化项目结构,配置.gitignore,重命名配置文件"

🔄 第二阶段:撤销与恢复

练习 3:各种撤销操作

1-2:创建提交历史

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
cd ../

mkdir exercise3
cd exercise3
git init

# 第一章
echo "# 第一章:启程" > story.txt
git add story.txt
git commit -m "添加第一章"

# 第二章
echo "" >> story.txt
echo "# 第二章:冒险开始" >> story.txt
git add story.txt
git commit -m "添加第二章"

# 第三章
echo "" >> story.txt
echo "# 第三章:深入探索" >> story.txt
git add story.txt
git commit -m "添加第三章"

# 查看历史
git log --oneline
# 应该有3次提交

操作 1:checkout 撤销工作区修改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 修改文件但未暂存
echo "# 错误的内容" >> story.txt

# 查看状态
git status
# 显示story.txt有修改但未暂存

# 撤销工作区修改
git checkout -- story.txt

# 验证文件是否恢复
git status
# 应该显示working tree clean
cat story.txt
# 应该只有三章内容,没有"错误的内容"

操作 2:reset 撤销暂存区修改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 修改并暂存
echo "# 第四章:新的篇章" >> story.txt
git add story.txt

# 查看状态
git status
# 显示story.txt有修改已暂存

# 从暂存区移除
git reset HEAD story.txt

# 查看状态
git status
# 显示story.txt有修改但未暂存

# 文件内容还在吗?
cat story.txt | tail -1
# 应该显示"# 第四章:新的篇章"

操作 3:revert 撤销提交

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 先提交刚才的修改
git add story.txt
git commit -m "添加第四章"

# 查看历史
git log --oneline
# 应该有4次提交

# 撤销倒数第二次提交(第三章)
git revert HEAD~1
# 会打开编辑器,保存退出

# 查看文件内容
cat story.txt
# 第三章应该被删除了

# 查看历史
git log --oneline
# 应该有5次提交(包括revert那次)

操作 4:hard reset

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 创建新文件并提交
echo "测试内容" > test.txt
git add test.txt
git commit -m "添加测试文件"

# 查看文件是否存在
ls
# 应该有story.txt和test.txt

# 硬重置到上一个提交
git reset --hard HEAD~1

# 再次查看
ls
# test.txt应该消失了!
git log --oneline
# 只有到revert的提交

# 警告:这是不可逆的,test.txt完全丢失了

🌿 第三阶段:分支管理

练习 4:基础分支操作

1-2:初始化项目

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
cd ../

mkdir exercise4
cd exercise4
git init

# 创建基础框架
mkdir src tests docs
echo "项目名称:MyApp" > README.md
echo "version = '1.0.0'" > config.py

git add .
git commit -m "初始化项目结构"

3-5:开发登录功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 创建登录功能分支
git checkout -b feature/login

# 开发登录功能
cat > src/auth.py << EOF
def login(username, password):
    """用户登录功能"""
    if username == "admin" and password == "123456":
        return True
    return False

def logout():
    """用户登出"""
    return "Logged out"
EOF

git add src/auth.py
git commit -m "添加基础登录功能"

# 继续开发
echo "LOGIN_ATTEMPTS_LIMIT = 5" >> src/auth.py
git add src/auth.py
git commit -m "添加登录尝试限制"

# 添加测试
echo "import auth" > tests/test_auth.py
git add tests/test_auth.py
git commit -m "添加登录功能测试"

4-5:开发支付功能

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 切换回main分支
git checkout main

# 创建支付功能分支
git checkout -b feature/payment

# 开发支付功能
cat > src/payment.py << EOF
def process_payment(amount, card_number):
    """处理支付"""
    if len(card_number) != 16:
        return False
    return True

def refund(transaction_id):
    """退款处理"""
    return f"Refund for {transaction_id}"
EOF

git add src/payment.py
git commit -m "添加支付处理功能"

# 继续开发
echo "PAYMENT_GATEWAY = 'Stripe'" >> src/payment.py
git add src/payment.py
git commit -m "配置支付网关"

6-7:合并与冲突

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 合并登录功能到main
git checkout main
git merge feature/login -m "合并登录功能"
# 应该会显示"Fast-forward"

# 尝试合并支付功能(模拟冲突)
# 先修改main中的README
echo "项目包含登录和支付功能" >> README.md
git add README.md
git commit -m "更新README说明"

# 在支付分支也修改README
git checkout feature/payment
echo "支付功能使用Stripe网关" >> README.md
git add README.md
git commit -m "更新支付功能说明"

# 尝试合并到main(会产生冲突)
git checkout main
git merge feature/payment
# 预期:CONFLICT (content): Merge conflict in README.md

8:解决冲突

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 查看冲突文件
cat README.md
# 会显示类似:
# <<<<<<< HEAD
# 项目包含登录和支付功能
# =======
# 支付功能使用Stripe网关
# >>>>>>> feature/payment

# 手动解决冲突(编辑README.md)
# 改为:项目包含登录和支付功能,支付功能使用Stripe网关

# 删除冲突标记后
git add README.md
git status
# 应该显示:All conflicts fixed

git commit -m "解决合并冲突,整合支付功能"

练习 5:高级分支操作

场景 1:rebase 练习

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
cd ../

mkdir exercise5
cd exercise5
git init

# 创建基础提交
echo "初始文件" > file1.txt
git add .
git commit -m "A: 初始提交"

echo "更多内容" >> file1.txt
git add .
git commit -m "B: main更新1"

echo "main的更新" >> file1.txt
git add .
git commit -m "C: main更新2"

# 创建feature分支并添加提交
git checkout -b feature HEAD~2  # 回到提交A

echo "功能开发1" > file2.txt
git add .
git commit -m "D: feature功能1"

echo "功能开发2" >> file2.txt
git add .
git commit -m "E: feature功能2"

# 查看当前结构
git log --oneline --graph --all
# 应该是分叉的结构

# 执行rebase
git rebase main
# 注意观察发生了什么

# 再次查看
git log --oneline --graph
# feature分支应该在main的末端

场景 2:cherry-pick 练习

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 继续在上面的项目中
# 创建一些有意义的提交
git checkout -b bug-fixes

echo "修复bug #1" > bugfix1.txt
git add .
git commit -m "修复bug #1: 空指针异常"

echo "修复bug #2" > bugfix2.txt
git add .
git commit -m "修复bug #2: 内存泄漏"

echo "修复bug #3" > bugfix3.txt
git add .
git commit -m "修复bug #3: 性能问题"

# 查看提交哈希
git log --oneline
# 复制第二个提交的哈希(bug #2)

# 切换到main分支,只应用bug #2的修复
git checkout main
git cherry-pick <刚才复制的哈希值>
# 注意:<刚才复制的哈希值>替换为实际的哈希值,如a1b2c3d

# 验证
git log --oneline
# main分支应该只有bug #2的修复
ls
# 应该只有bugfix2.txt

场景 3:stash 练习

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 继续使用上面的项目
git checkout feature

# 开始工作
echo "正在开发新功能..." > new_feature.txt

# 突然需要修复紧急bug
git status
# 显示有未提交的修改

# 保存当前工作
git stash save "保存新功能开发进度"

# 验证工作区是否干净
git status
# 应该是干净的

# 切换到main分支修复bug
git checkout main
echo "紧急修复" > hotfix.txt
git add .
git commit -m "紧急修复生产环境bug"

# 返回feature分支恢复工作
git checkout feature

# 查看stash列表
git stash list
# 显示:stash@{0}: On feature: 保存新功能开发进度

# 恢复stash
git stash pop
# 自动应用并删除stash

# 验证
git status
# 应该显示有未暂存的修改
ls
# 应该有new_feature.txt

🌐 第四阶段:远程操作

练习 6:GitHub/GitLab 操作

注意:这部分需要真实的 GitHub/GitLab 账户

1-3:创建和关联远程仓库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
cd ../

mkdir exercise6
cd exercise6
git init

# 本地开发
echo "# 远程仓库练习项目" > README.md
echo "print('Hello Remote')" > main.py
git add .
git commit -m "初始化项目"

# 关联远程仓库(假设已在GitHub创建了仓库)
# 替换URL为你的实际仓库URL
git remote add origin https://github.com/你的用户名/git-practice-remote.git

# 第一次推送
git push -u origin main
# 需要输入用户名和密码/Token

4-5:远程修改和拉取

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 模拟其他人在远程修改(或自己在网页修改)
# 先在网页上修改README.md,添加一行:"## 远程修改的内容"

# 本地拉取更改
git pull origin main
# 或 git fetch + git merge

# 查看文件
cat README.md
# 应该包含你网页上添加的内容

6:模拟团队协作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 创建开发分支
git checkout -b develop

# 本地开发
echo "新功能开发" > feature.txt
git add .
git commit -m "开发新功能"

# 推送分支
git push -u origin develop

# 模拟另一个开发者(在另一个目录)
cd ../
mkdir another-developer
cd another-developer
git clone https://github.com/你的用户名/git-practice-remote.git
cd git-practice-remote

# 也在develop分支开发
git checkout develop
echo "另一个开发者的修改" >> feature.txt
git add .
git commit -m "开发者B的修改"
git push origin develop
# 这个应该成功

# 回到第一个开发者目录
cd ../../exercise6

# 尝试推送(会产生冲突)
echo "我的更多修改" >> feature.txt
git add .
git commit -m "开发者A的更多修改"
git push origin develop
# 预期:被拒绝,需要先拉取

# 拉取并解决冲突
git pull origin develop
# 会有冲突,手动解决
# 编辑feature.txt,删除冲突标记

git add feature.txt
git commit -m "解决合并冲突"
git push origin develop

🏷️ 第五阶段:标签与发布

练习 7:版本标签

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
cd ../

mkdir exercise7
cd exercise7
git init

# 创建一些提交作为版本基础
echo "初始代码" > app.js
git add .
git commit -m "v1.0.0基础版本"

# 打标签
git tag v1.0.0

# 开发新功能
echo "新功能A" >> app.js
git add .
git commit -m "添加功能A"

echo "新功能B" >> app.js
git add .
git commit -m "添加功能B"
git tag v1.1.0

# bug修复
echo "修复已知问题" >> app.js
git add .
git commit -m "修复bug #123"
git tag v1.1.1

# 查看所有标签
git tag -l
# 应该显示:v1.0.0 v1.1.0 v1.1.1

# 查看标签详细信息
git show v1.1.0

# 推送标签到远程(如果有远程仓库)
# git push origin v1.0.0
# git push origin --tags  # 推送所有标签

# 删除标签(本地)
git tag -d v1.1.1

# 验证
git tag -l
# v1.1.1应该消失了

🎯 综合实战项目

最终练习:完整开发流程

由于篇幅限制,这里给出关键步骤框架:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 1. 项目初始化
mkdir todo-app
cd todo-app
git init
echo "# 待办事项应用" > README.md
mkdir src tests
git add .
git commit -m "项目初始化"

# 2. 创建.gitignore
cat > .gitignore << EOF
__pycache__/
*.pyc
.env
.DS_Store
EOF

# 3. 建立开发分支
git checkout -b develop

# 4. 功能分支开发流程
# 功能1:添加任务
git checkout -b feature/add-task
# 开发代码...
git add .
git commit -m "实现添加任务功能"
git checkout develop
git merge feature/add-task --no-ff -m "合并添加任务功能"

# 功能2:删除任务
git checkout -b feature/delete-task
# 开发代码...
git add .
git commit -m "实现删除任务功能"
# 使用rebase保持历史整洁
git rebase develop
git checkout develop
git merge feature/delete-task --no-ff -m "合并删除任务功能"

# 5. 版本发布
git checkout main
git merge develop --no-ff -m "发布v1.0.0"
git tag v1.0.0

# 6. Hotfix流程
git checkout main
git checkout -b hotfix/urgent-bug
# 修复bug...
git add .
git commit -m "修复紧急bug #456"
git checkout main
git merge hotfix/urgent-bug -m "合并紧急修复"
git tag v1.0.1
git checkout develop
git merge hotfix/urgent-bug -m "同步紧急修复到develop分支"

# 可视化查看
git log --oneline --graph --all

💡 关键概念验证练习

1. 理解三个区域

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
mkdir test-areas
cd test-areas
git init

# 工作区修改
echo "line1" > file.txt
git status  # untracked

# 暂存区
git add file.txt
git status  # changes to be committed

# 仓库
git commit -m "commit 1"
git status  # clean

# 再次修改
echo "line2" >> file.txt
git diff  # 工作区 vs 暂存区
git diff --cached  # 暂存区 vs 仓库
git diff HEAD  # 工作区 vs 仓库

2. HEAD 和分支指针

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查看HEAD指向
cat .git/HEAD

# 创建分支时发生了什么
git branch new-branch
cat .git/refs/heads/new-branch

# 切换分支时HEAD的变化
git checkout new-branch
cat .git/HEAD  # 指向ref: refs/heads/new-branch

3. 对象存储

1
2
3
4
5
6
# 查看对象
git hash-object file.txt
# 计算出的哈希值,可以在.git/objects/中找到

# 查看对象内容
git cat-file -p <hash>

🎮 Git 闯关练习对应命令

根据你的笔记,这些是闯关练习中的关键命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 基础关卡
git commit
git branch newImage
git checkout newImage && git commit
git checkout -b bugFix
git merge bugFix
git rebase main

# 相对引用
git checkout HEAD^
git checkout HEAD~3
git branch -f main HEAD~3

# 远程操作
git clone <url>
git fetch
git pull
git push
git push origin feature

# 高级操作
git cherry-pick C2 C4
git rebase -i HEAD~4
git tag v1 C1
git describe <commit>

📝 快速检查清单

在每个练习完成后,检查你是否掌握了:

  1. ✅ 能初始化仓库并提交更改
  2. ✅ 能查看状态、差异和历史
  3. ✅ 能创建、切换、合并分支
  4. ✅ 能解决合并冲突
  5. ✅ 能使用 stash 暂存工作
  6. ✅ 能使用 rebase 整理历史
  7. ✅ 能关联和操作远程仓库
  8. ✅ 能创建和管理标签
  9. ✅ 理解 reset、checkout、revert 的区别
  10. ✅ 能进行完整的 Git 工作流程

记住,真正的掌握来自于反复练习和在实际项目中应用。每个命令至少练习 3-5 次,直到你能不查笔记就能正确使用!