简介:Git 到底是什么(先建立正确认知)
Git 是一个版本管理工具 ,作用就像游戏存档:
-
每写完一段代码,就"存一个档"(叫 commit)
-
任何时候都能回到之前的存档
-
能看"谁、什么时候、改了什么"
它管的是文件的历史版本。
三个"地方"(最核心的概念,务必记住)
你的代码改动,会依次经过三个地方:
① 工作区(你的文件夹) --git add--> ② 暂存区(待提交清单) --git commit--> ③ 本地仓库(存档历史) --git push--> ④ 远程仓库(Gitee)
-
工作区:你正在编辑的文件
-
暂存区:你"选定要存档"的文件清单
-
本地仓库:已经存档的历史
-
远程仓库 (Gitee):用
git push把本地存档同步上去。
记住 4 个核心命令
| 命令 | 动作 | 通俗比喻 |
|---|---|---|
git status |
看状态 | 看看现在什么情况 |
git add |
暂存 | 把文件放进"待存档"篮子 |
git commit |
提交 | 存档 |
git push |
推送 | 把存档同步到 Gitee |
第 1 章:开始前的准备(只做一次)
1.1 确认 Git 已安装
git --version
看到版本号(如 git version 2.50.1)就说明装好了。
1.2 配置你的身份
git config --global user.name "Alice"
git config --global user.email "Alice@example.com"
【含义】这两行告诉 Git"你是谁",每次存档都会记上你的名字。--global 表示对电脑上所有项目生效,只需设置一次。
⚠️ 这里的名字只是存档署名 ,随便填都行,不是 Gitee 登录账号。
1.3 拿到 Gitee 仓库地址
打开 Gitee 上你建的仓库页面 → 点 「克隆/下载」 → 复制 HTTPS 地址,形如:
https://gitee.com/你的用户名/仓库名.git
https://gitee.com/fencecat/todo.git
第 2 章:把仓库"拉"到本地(git clone)
cd ~ # 进入你的家目录(放代码的地方)
# 克隆:把 Gitee 上的仓库复制到本地
struggle@struggledeMac-mini my-todo % git clone https://gitee.com/fencecat/todo.git
Cloning into 'todo'...
Username for 'https://gitee.com': fencecat
Password for 'https://fencecat@gitee.com':
warning: You appear to have cloned an empty repository.
struggle@struggledeMac-mini my-todo %
#文件目录下有克隆的仓库目录
struggle@struggledeMac-mini my-todo % ls
todo
https://gitee.com/你的用户名/仓库名.git
# 进入克隆出来的文件夹
cd todo
【含义】git clone 地址 会做两件事:
-
本地创建一个和仓库同名的文件夹
-
把这个文件夹变成一个"本地仓库"(里面有个隐藏的
.git文件夹,存放所有历史)
如果仓库是空的 ,会看到提示 warning: You appear to have cloned an empty repository.------正常,意思是"这是空仓库"。
第 3 章:写第一份代码
struggle@struggledeMac-mini todo % vim hello.py
struggle@struggledeMac-mini todo % git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.py
nothing added to commit but untracked files present (use "git add" to track)
在文件夹里新建一个文件 hello.py,内容:
print("你好,世界") 然后运行: git status 会看到类似:
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.py
【含义】hello.py 显示 Untracked = Git 还不认识这个新文件 (没被管理)。下一步用 git add 让它被管理。
第 4 章:暂存(git add)
git add hello.py 再运行:git status
struggle@struggledeMac-mini todo % git add hello.py
struggle@struggledeMac-mini todo % git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.py
struggle@struggledeMac-mini todo %
【含义】hello.py 从 Untracked 变成 Changes to be committed,意思是"已经放进待存档篮子,准备存档"。
第 5 章:提交/存档(git commit)
git commit -m "第一次提交:hello 程序"
struggle@struggledeMac-mini todo % git commit -m "第一次提交:hello 程序"
[master (root-commit) d333df5] 第一次提交:hello 程序
1 file changed, 1 insertion(+)
create mode 100644 hello.py
【含义】
-
git commit= 存档 -
-m "..."= 存档说明(message),写清楚这次改了什么
看历史:
git log --oneline
truggle@struggledeMac-mini todo % git log --oneline
d333df5 (HEAD -> master) 第一次提交:hello 程序
struggle@struggledeMac-mini todo %
会看到:a1b2c3d 第一次提交:hello 程序
前面那串 a1b2c3d 是这次存档的编号(哈希),git log 就是"翻存档记录"。
第 6 章:推送到 Gitee(git push)
git push -u origin master
struggle@struggledeMac-mini todo % git push -u origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 261 bytes | 261.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Powered by GITEE.COM [1.1.23]
remote: Set trace flag c340d382
To https://gitee.com/fencecat/todo.git
* [new branch] master -> master
branch 'master' set up to track 'origin/master'.
struggle@struggledeMac-mini todo %
【含义】
-
git push= 把本地存档同步到 Gitee -
origin= 远程仓库别名(clone 时自动起的,指 Gitee 那个仓库) -
master= 分支名(主干分支) -
-u= 关联起来,以后只需敲git push
第一次会要登录:用户名 = Gitee 账号名,密码 = Gitee 登录密码(输密码时屏幕不显示任何字符,正常,盲打后回车)。
成功后刷新 Gitee 网页,就能看到 hello.py 和这次提交了!🎉
第 7 章:日常开发循环(最重要的习惯)
以后每次改代码,都是这套循环:
# 1. 改代码(用编辑器改文件)
# 2. 看改了什么
git status # 看哪些文件变了
git diff # 看具体改了哪几行
# 3. 暂存
git add 文件名 # 或 git add . 表示全部暂存
# 4. 提交
git commit -m "说明这次改了什么"
# 5. 推送
git push
练习 :给 hello.py 加一个函数,然后完整走一遍这个循环,再刷新 Gitee 看看是不是多了一次提交。
bash
struggle@struggledeMac-mini todo % vim hello.py
struggle@struggledeMac-mini todo % git status
On branch master
Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py
no changes added to commit (use "git add" and/or "git commit -a")
struggle@struggledeMac-mini todo % git diff
diff --git a/hello.py b/hello.py
index 1a619a3..862876a 100644
--- a/hello.py
+++ b/hello.py
@@ -1 +1 @@
-print("你好,世界")
+print("你好,世界!")
struggle@struggledeMac-mini todo % git add .
struggle@struggledeMac-mini todo %
struggle@struggledeMac-mini todo % git commit -m "加了标点符号"
[master 08d3aa5] 加了标点符号
1 file changed, 1 insertion(+), 1 deletion(-)
struggle@struggledeMac-mini todo % git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 285 bytes | 285.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Powered by GITEE.COM [1.1.23]
remote: Set trace flag 9f45f0a3
To https://gitee.com/fencecat/todo.git
d333df5..08d3aa5 master -> master
第 8 章:分支✨(进阶)
分支 = 给自己一个"独立工作台",改坏了不影响主干 main。真实开发里永远不要直接在 main 上改。
git switch -c feature/新功能 # 新建并切换分支(-c = create)
# ...在这个分支上改代码、add、commit...
git push -u origin feature/新功能 # 推分支到 Gitee
git switch main # 切回主干
git merge feature/新功能 # 把功能合并进主干
git push # 推送合并结果
详细的分支、合并、冲突教程见
git-basics-todo-scenario.md和git-merge-conflict.md。
📋 实操步骤(在我的todo仓库中执行)
第一步:创建并切换到新分支
bash
# 确保在 todo 仓库目录下
struggle@struggledeMac-mini todo % pwd
/tmp/git-basics/my-todo/todo
# 查看当前分支(应该显示 * main)
struggle@struggledeMac-mini todo % git branch
* master
# 创建并切换到新分支 feature/hello
git switch -c feature/hellostruggle@struggledeMac-mini todo % git switch -c feature/hello
Switched to a new branch 'feature/hello'
第二步:在新分支上开发(修改代码)
bash
# 创建一个新文件(模拟新功能开发)
struggle@struggledeMac-mini todo % echo "print('Hello from feature branch!')" > hello.py
# 查看状态(应该显示新文件未被追踪)
struggle@struggledeMac-mini todo % git status
On branch feature/hello
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: hello.py
no changes added to commit (use "git add" and/or "git commit -a")
# 添加并提交
struggle@struggledeMac-mini todo % git add hello.py
struggle@struggledeMac-mini todo % git commit -m "feat: 添加 hello.py 新功能"
[feature/hello f46ee98] feat: 添加 hello.py 新功能
1 file changed, 1 insertion(+), 1 deletion(-)
# 再修改一下README(模拟功能迭代)
struggle@struggledeMac-mini todo % echo "# 这是我在 feature 分支添加的注释" >> README.md
struggle@struggledeMac-mini todo % git add README.md
struggle@struggledeMac-mini todo % git commit -m "docs: 更新 README 说明"
[feature/hello 8197774] docs: 更新 README 说明
1 file changed, 1 insertion(+)
create mode 100644 README.md
第三步:推送分支到 Gitee
bash
# 推送到远程,并建立追踪关系
struggle@struggledeMac-mini todo % git push -u origin feature/hello
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 10 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 614 bytes | 614.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Powered by GITEE.COM [1.1.23]
remote: Set trace flag 154110a6
remote: Create a pull request for 'feature/hello' on Gitee by visiting:
remote: https://gitee.com/fencecat/todo/pull/new/fencecat:feature/hello...fencecat:master
To https://gitee.com/fencecat/todo.git
* [new branch] feature/hello -> feature/hello
branch 'feature/hello' set up to track 'origin/feature/hello'.
第四步:切回主干,合并功能
bash
# 切回 master 分支
struggle@struggledeMac-mini todo % git switch master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
# 确认你在 master 分支上
struggle@struggledeMac-mini todo % git branch
feature/hello
* master
# 把 feature/hello 分支的修改合并进来
struggle@struggledeMac-mini todo % git merge feature/hello
Updating 08d3aa5..8197774
Fast-forward
README.md | 1 +
hello.py | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 README.md
struggle@struggledeMac-mini todo % git push
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Powered by GITEE.COM [1.1.23]
remote: Set trace flag d24106ad
To https://gitee.com/fencecat/todo.git
08d3aa5..8197774 master -> master
第五步:推送合并结果到 Gitee
bash
# 推送本地的 master 分支到远程
struggle@struggledeMac-mini todo % git push
Everything up-to-date
⚠️ 如果合并时出现冲突怎么办?
合并冲突是团队协作中的常态。如果合并时提示冲突(CONFLICT),你可以:
bash
# 1. 查看冲突文件
git status
# 2. 手动编辑冲突文件(IDE 会高亮标记冲突区域)
# 3. 解决冲突后,重新标记为已解决
git add <冲突文件>
git commit -m "合并 feature/hello 并解决冲突"
# 4. 继续推送
git push
💡 一个实用的分支管理命令
bash
# 查看所有分支及其最后一次提交
git branch -v
# 删除本地已合并的分支(清理用)
git branch -d feature/hello
# 删除远程已合并的分支
git push origin --delete feature/hello
第 9 章:撤销(救命命令)
bash
git restore 文件名 # 改错了,还没 add:丢弃改动
git restore --staged 文件名 # 已经 add 了:撤回暂存(内容还在)
git revert 提交哈希 # 已经 commit 了:安全撤销这次提交
第 10 章:命令速查表
| 想做什么 | 命令 |
|---|---|
| 拿代码到本地 | git clone 地址 |
| 看状态 | git status |
| 看历史 | git log --oneline |
| 看改了什么 | git diff |
| 暂存 | git add 文件名(或 git add .) |
| 提交 | git commit -m "说明" |
| 推送 | git push |
| 拉取更新 | git pull |
| 建/切分支 | git switch -c 分支 / git switch 分支 |
| 合并 | git merge 分支 |
| 丢弃改动 | git restore 文件名 |
| 撤销提交 | git revert 哈希 |
第 11 章:常见报错与解决
| 报错 | 原因 | 解决 |
|---|---|---|
Authentication failed |
账号密码不对 | 用户名用 Gitee 账号名;密码用登录密码(或私人令牌) |
rejected ... non-fast-forward |
远程有本地没有的提交 | 先 git pull --rebase 再 git push |
Untracked files |
新文件没被管理 | 正常,git add 即可 |
no changes added to commit |
没暂存就想提交 | 先 git add 再 git commit |
关于rejected ... non-fast-forward场景:
non-fast-forward = 你的历史和远程"分叉"了 (远程有同事的新提交,你本地也有自己的新提交,两边各走各的),Git 不敢直接覆盖,所以拒绝你的 push。
为什么叫 "fast-forward"(快进)
想象提交历史是一条线。如果远程是 v1,你本地是 v1 → 你的提交,那 push 就是"顺着线往前走",Git 可以直接快进,没矛盾。
但现在的情况是:
复制
* 你:也加了一行 ← 你的本地提交(基于 v1)
|
v1 ──┤
|
* 同事:加了一行 ← 同事已推到远程(也基于 v1)
两边都从 v1 各自往前走了一步,分叉了 。Git 无法"快进",只能停下来让你处理 → 报 non-fast-forward。
解决:git pull --rebase
它的作用是:把你的提交"搬"到远程最新提交的上面,把分叉捋成一条直线:
复制
处理前(分叉) 处理后(一条直线,可 push)
* 你 * 你:也加了一行 ← 你的提交被搬到同事之上
| * 同事 * 同事:加了一行 ← 远程最新
|/ * v1
* v1
现在你的历史 = 远程历史 + 你的新提交,就能"快进"了,git push 成功。
bash
git pull --rebase origin master # 先拉取远程,把自己的提交"搬"到上面
git push # 再推送,成功