avatar😊
w乐意wlyのblog

与你相遇 好幸运

欢迎来到我的小窝

Git的简单使用

为什么要用Git

想象你正在写一篇论文:

  • 论文_初稿.doc
  • 论文_修改1.doc
  • 论文_最终版.doc
  • 论文_最终版_绝对不改.doc

时间一长,你不知道哪个才是最新版,也不敢删掉旧的。Git 就是帮你管理这些“版本”的工具,它会记录每次修改的内容、时间、作者,让你能随时回到过去的某个状态,也能和别人并行合作,最后合并到一起。

核心概念先有个印象:

  • 仓库(Repository):一个被 Git 管理的项目目录,里面藏着完整的历史记录。
  • 提交(Commit):一次“保存快照”的操作,就像游戏的存档点。

安装并配置Git

环境:WSL2,Ubuntu24.04

打开终端,先更新包列表,再安装 Git:

bash
sudo apt update
sudo apt install git -y

安装完成后,检查是否成功:

bash
git --version

你应该会看到类似 git version 2.43.0 的输出(版本号以实际为准)。

配置身份

Git 每次提交都会记录“谁做的”,所以要先告诉 Git 你的名字和邮箱。这个信息会随提交一起被永久记录在历史里。

在终端依次执行(把名字和邮箱换成你自己的,建议邮箱使用 GitHub 注册邮箱):

bash
git config --global user.name "你的名字"
git config --global user.email "你的邮箱@example.com"

--global 表示这个配置对你整个系统的当前用户生效,所有 Git 仓库都会默认使用这个身份。

验证一下配置是否生效:

bash
git config --global --list

你会看到类似输出:

bash
user.name=你的名字
user.email=你的邮箱@example.com

可选设置

为了让以后的输出更易读,建议打开命令行颜色高亮:

bash
git config --global color.ui auto

在 Ubuntu 终端中,这会让 diff、status 等命令的输出用不同颜色标记增、删、改,看起来一目了然。

创建仓库与第一次提交

创建第一个项目目录

首先,我们在主目录下建一个练习文件夹,叫 my-first-repo

bash
cd ~
mkdir my-first-repo
cd my-first-repo

初始化仓库

让 Git 接管这个目录:

bash
git init

你会看到类似输出:

bash
Initialized empty Git repository in /home/你的用户名/my-first-repo/.git/

这行字告诉你:仓库诞生了。它会在这个目录下创建一个隐藏文件夹 .git,里面存着 Git 需要的所有历史数据。用 ls -a 可以看到它。

重要认知git init 后,这个目录就变成了工作区(Working Directory),里面的 .git 文件夹就是仓库(Repository)。

Git 的三个区域

继续之前,必须先把这三个区域记在心里,这是 Git 的灵魂:

  1. 工作区(Working Directory)

    • 就是你能看到的项目文件夹,你直接在这里增、删、改文件。
    • Git 会监视这里的变化,但不会自动记录。
  2. 暂存区(Staging Area / Index)

    • 你希望被记录的那些修改,需要先“添加”到这个区域。
    • 可以理解为一张“准备提交的快照暂存清单”。
    • 使用 git add 会把文件从工作区送到暂存区。
  3. 仓库(Repository / Commit History)

    • .git 文件夹里的东西,藏着所有历史提交。
    • 使用 git commit 会把暂存区的内容永久保存为一个“提交”。

工作流程是:

text
工作区 ──(git add)──> 暂存区 ──(git commit)──> 仓库

记住这个流程,后面你就能理解每一个命令在干什么。

创建第一个文件

在工作区创建一个文件 hello.txt

bash
echo "Hello, Git" > hello.txt

现在用 git status 看一眼仓库状态:

bash
git status

输出会显示:

bash
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        hello.txt

nothing added to commit but untracked files present (use "git add" to track)

Git 告诉你:

  • 当前在 master 分支(这是默认的主分支名)。
  • 还没有任何提交(No commits yet)。
  • hello.txt 是未跟踪文件(Untracked),工作区有个新文件,但 Git 还没管它。

把文件加入暂存区

让 Git 开始跟踪 hello.txt

bash
git add hello.txt

再运行 git status 看看变化,现在输出像这样:

bash
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   hello.txt

hello.txt 现在在暂存区 了,状态是 “new file”,准备被提交。

第一次提交

把暂存区的内容永久保存到仓库中:

bash
git commit -m "第一次提交:添加 hello.txt"
  • -m 后面跟的是提交信息(commit message),用来描述这次做了什么修改。
  • 提交信息必须写,而且最好写清楚,这是以后看历史的你会感谢你的事。

执行后你会看到:

bash
[master (root-commit) xxxxxxx] 第一次提交:添加 hello.txt
 1 file changed, 1 insertion(+)
 create mode 100644 hello.txt

这意味着:

  • master 分支上生成了第一个提交(root-commit 表示它是整个历史的根)。
  • 一个文件改变了,添加了一行内容。
  • 提交的哈希值(一串十六进制字符)已经生成,唯一标识这次提交。

查看历史

现在看看仓库里记录了什么:

bash
git log

输出类似:

bash
commit a1b2c3d4e5f...(一串哈希值)
Author: 你的名字 <你的邮箱@example.com>
Date:   Mon Apr 27 10:00:00 2026 +0800

    第一次提交:添加 hello.txt

你看到了:

  • 提交的唯一哈希值(不用记全,前几位就能区分)
  • 作者和日期信息,正是你第一章配置的身份
  • 提交信息

q 键可以退出 log 的浏览模式。

巩固流程

趁热打铁,再做一轮完整的修改→暂存→提交。

  1. 修改文件:向 hello.txt 追加一行
bash
echo "Git is fun" >> hello.txt
  1. 查看状态:
bash
git status
  1. 查看具体改动:
bash
git diff

能看到你添加了什么内容(以 + 开头的绿字)。

  1. 加入暂存区:
bash
git add hello.txt
  1. 提交:
bash
git commit -m "添加第二行:Git is fun"
  1. 再次查看历史:
bash
git log

现在会看到两次提交,从新到旧排列。最新的在上面。

深入暂存区与文件管理

接下来会教你后悔药怎么吃——修改错了怎么撤,提交反悔了怎么退,还会让你真正看透 git diff 的各种用法。先确认一下历史:

bash
cd ~/my-first-repo
git log --oneline

你应该能看到类似两条记录(哈希值会不同):

bash
a1b2c3d 添加第二行:Git is fun
e5f6g7h 第一次提交:添加 hello.txt

git diff 的三种常用姿势

git diff 是“对比神器”,不同参数对比不同区域。

  1. 工作区 vs 暂存区git diff,无参数)

先制造一个工作区修改:

bash
echo "第三行:learning diff" >> hello.txt

现在修改只存在工作区,未暂存。运行:

bash
git diff

输出会显示什么?以 + 开头的绿字是你新增的内容,前面带有 @@ 的行是位置标记。这个命令对比的是工作区和暂存区(如果暂存区为空,就是和最新提交比)。 因为暂存区现在还是原来的版本,所以你能看到新增的“第三行”。

  1. 暂存区 vs 最新提交git diff --staged

先把刚才的修改加入暂存区:

bash
git add hello.txt

现在再运行 git diff 会发现没有任何输出,因为工作区和暂存区内容一致了。但你想看 暂存区和最新提交相比有什么变化,就用:

bash
git diff --staged

(也可以用 git diff --cached,一个意思。) 这次你会看到刚才添加的 +第三行:learning diff,说明暂存区比当前提交多了这一行。

  1. 工作区 vs 最新提交git diff HEAD

在工作区再追加一行(暂存区没变):

bash
echo "第四行:will be unstaged" >> hello.txt

现在工作区比暂存区多了一行,暂存区又比最新提交多了一行。直接比较工作区和最新提交:

bash
git diff HEAD

你会看到两条新增行:一条是之前暂存的“第三行”,另一条是刚才加的“第四行”。 HEAD 总是指向当前分支的最新提交,所以这个命令跳过了暂存区,直接拿工作区和最后一次 commit 比。

小总结

  • git diff → 工作区 vs 暂存区
  • git diff --staged → 暂存区 vs HEAD
  • git diff HEAD → 工作区 vs HEAD

撤销工作区的修改

假设你现在发现“第四行”写错了,想丢弃工作区的这个修改,恢复成暂存区(或最新提交)的样子。在丢弃之前,再看一眼状态确认:

bash
git status

你会看到 hello.txt 既有暂存的修改(绿色 "modified"),又有未暂存的修改(红色 "modified")。现在我们丢弃工作区的修改(即刚才加的那行“第四行”):

bash
git checkout -- hello.txt

或者新版本 Git 也可以使用等价命令 git restore hello.txt。执行后,查看文件内容:

bash
cat hello.txt

你会发现“第四行”消失了,文件内容回到了暂存区保存的版本(只有三行)。再用 git diff HEAD 看,现在只显示暂存区里的“第三行”,说明工作区已经恢复到了暂存区的状态。

注意:这个操作会永久丢失工作区的未提交修改,而且很难恢复(除非用 IDE 的本地历史)。请一定确认要丢弃再执行。

取消暂存

当前的暂存区里还保存着“第三行”的修改。如果你决定:先不把第三行放在这次提交里,但保留在工作区,该怎么操作?

我们需要把文件从暂存区移回工作区。

bash
git reset HEAD hello.txt

(新版本 Git 也可以用 git restore --staged hello.txt) 运行之后,git status 你会看到:

  • “Changes to be committed” 里不再有 hello.txt
  • hello.txt 出现在 “Changes not staged for commit” 里,而且还是被修改过的状态

也就是说,文件从暂存区退回了工作区,修改本身没有丢失。

此时如果你又后悔了,可以再次 git add 把它暂存回去。如果你连这个修改都不想要了,可以用上一步的 git checkout -- hello.txt 彻底丢弃。

git reset 的三种模式

比撤销文件更彻底的,是撤销一次提交。我们先创建一个“临时”提交来演示。

先把刚才的第三行暂存并提交:

bash
git add hello.txt
git commit -m "添加第三行:learning diff"

现在 git log --oneline 会显示三个提交。

接下来,我们要“退回”到上一个提交。git reset 可以移动当前分支指针,有三种常用模式:

模式效果提交暂存区工作区
--soft只撤销提交,改动留在暂存区回退保留保留
--mixed(默认)撤销提交和暂存,改动留在工作区回退清空保留
--hard全部撤销,工作区也清掉回退清空清除

1. --soft:提交后悔了,但想重新修改提交信息

执行(注意:把 HEAD~1 指向上一个提交):

bash
git reset --soft HEAD~1

git status 查看状态,你会看到 hello.txt 的修改仍然在暂存区(绿色,等待提交),但 git log 里“添加第三行”那个提交已经消失了。这就像刚 git add 完,还没来得及 commit。你可以修改提交信息,或添加其他文件后再提交。

2. --mixed(默认):提交错了,想把修改推回工作区重新编辑

先重新提交回去,以便演示:

bash
git commit -m "第三行(临时)"

现在再次回退,这次不给模式(默认就是 --mixed):

bash
git reset HEAD~1

git status,你会发现:

  • 暂存区是空的
  • hello.txt 的修改在工作区,“not staged”

这就是让你重新整理要提交的内容,再 addcommit

3. --hard:彻底放弃,回到干净状态(危险)

我们故意创建一个新文件并提交,然后彻底丢弃它。

bash
echo "临时垃圾文件" > junk.txt
git add junk.txt
git commit -m "添加一个不要的提交"

现在回退:

bash
git reset --hard HEAD~1

结果:

  • git log 看,那个提交消失了
  • junk.txt 被彻底删除,工作区干干净净

这就是 --hard 的威力:它会让你的工作区和暂存区完全和回退到的提交一致,未提交的修改也会丢失。一般情况下,不要轻易用 --hard,除非你十分确定可以丢弃。

分支的世界

分支是 Git 真正强大的地方——你可以在一条独立的线上开发新功能,不影响主线的稳定,成熟后再合并回去。

想象你在玩一种可以存档的冒险游戏。主线剧情是 master(或现在叫 main),当你走到某个关卡,突然想试试“如果我先去拿隐藏道具会怎样”,你就可以在那个时间点创建一个分支,在里面自由探索。就算玩砸了,主剧情毫发无损;如果探索成功,就把分支的进展合并回主线。

在 Git 里,分支仅仅是一个指向某个提交的轻量级指针。创建分支几乎瞬间完成,完全不占什么空间。

默认的主分支名在较新的 Git 中是 main,但你的仓库可能还是 master(取决于版本和配置)。我们这里以 master 为例,如果你看到的是 main,命令中替换即可。

查看分支

先看看当前仓库有哪些分支:

bash
git branch

输出:

bash
* master

前面的 * 表示你当前所在的分支——master

创建分支

假设我们想给 hello.txt 添加一个“作者署名”功能,但不想直接在主线上改。我们创建一个叫 feature/author 的新分支:

bash
git branch feature/author

git branch 再看一下分支列表:

bash
  feature/author
* master

新分支出现了,但 * 还停留在 master 上。创建分支并不会自动切换过去。

切换分支

要进入新分支工作,需要切换过去。推荐使用较新的命令 git switch(Git 2.23+),语义更清晰:

bash
git switch feature/author

你也可以使用传统的 git checkout feature/author,效果一样。现在再用 git branch 查看分支,* 已经移到 feature/author 前面了,表示你正在该分支上。

也可以同时创建并切换,用:

bash
git switch -c 分支名
# 或
git checkout -b 分支名

在分支上工作和提交

现在你在 feature/author 分支上。让我们修改 hello.txt,在文件末尾添加一行署名:

bash
echo "Author: GitLearner" >> hello.txt

git status 查看状态,暂存并提交:

bash
git add hello.txt
git commit -m "在 feature/author 分支添加作者署名"

git log --oneline 看一下这个分支的日志,你会看到,feature/authormaster 多了一个新提交。切回 master 看看文件:

bash
git switch master
cat hello.txt

你会发现,master 上的 hello.txt 完全没有那句 “Author: GitLearner”。因为那个修改只存在于 feature/author 分支上。这就是分支隔离的魔力。

合并分支

现在你觉得“署名功能”已经开发好了,想把它合并回主分支。首先确保你当前在想要合并到的目标分支上(即主分支 master):

bash
git switch master

然后执行合并:

bash
git merge feature/author

你会看到类似输出:

bash
Updating a1b2c3d..f6g7h8i
Fast-forward
 hello.txt | 1 +
 1 file changed, 1 insertion(+)

关键词:Fast-forward(快进合并)

为什么会快进?

因为 master 自从分出 feature/author 之后,自己没有产生任何新提交。feature/author 相当于在 master 的基础上直线往前走了几步。合并时,Git 只需要把 master 的指针直接“快进”到 feature/author 的最新提交即可,无需创建额外的“合并提交”。

此时的提交历史是一条直线:

text
第一次提交 → 添加第二行 → 添加第三行 → 在 feature/author 分支添加作者署名

此时 masterfeature/author 指向同一个提交。你可以用 git log --oneline 验证。再查看 hello.txt,署名已经出现了。

合并后分支清理

功能分支完成使命后,可以安全删除:

bash
git branch -d feature/author

查看分支列表,只剩 master。如果分支没有被合并,用 -d 会拒绝删除(防止误删),此时若确定不需要,可用 -D 强制删除。

理解“分叉”合并(非快进)

快进合并很干净,但现实里往往各个分支会同时推进,产生分叉历史。我们模拟一次。

  1. 创建并切换到新分支 feature/sign
bash
git switch -c feature/sign
  1. 在这个分支上修改,在 hello.txt 添加一行 “Sign: Best regards”:
bash
echo "Sign: Best regards" >> hello.txt
git add hello.txt
git commit -m "在 feature/sign 分支添加签名"
  1. 切回 master,在 master 上也做一个修改,比如新建一个文件 readme.md
bash
git switch master
echo "This is a README" > readme.md
git add readme.md
git commit -m "在 master 添加 README"

现在两个分支各自往前走了。看一下图景:masterfeature/sign 在 “添加作者署名” 这个提交之后分叉了。查看图形化日志(也可以不加 --graph,但图形很直观):

bash
git log --oneline --graph --all

你会看到类似:

bash
*  (HEAD -> master) 在 master 添加 README
| * (feature/sign) 在 feature/sign 分支添加签名
|/
* 在 feature/author 分支添加作者署名
* 添加第三行:learning diff
...

合并分叉:产生合并提交

现在把 feature/sign 合并回 master。 确保当前在 master

bash
git merge feature/sign

这一次,因为两个分支各自有新提交,Git 无法直接快进。它会生成一个 合并提交(merge commit),会把两个分支的修改合并到一起。

你会进入一个提交信息编辑界面(通常是 nano 或 vim)。如果是 nano,直接 Ctrl+X 退出保存就行;如果是 vim,按 :wq 保存退出。Git 已经默认填好了 “Merge branch 'feature/sign'”。

合并完成后,再看看日志图:

bash
git log --oneline --graph --all

你会看到类似:

bash
*    (HEAD -> master) Merge branch 'feature/sign'
|\
| * (feature/sign) 在 feature/sign 分支添加签名
* | master 添加 README
|/
* 在 feature/author 分支添加作者署名
...

这就是典型的功能分支开发与合并。

合并冲特与解决

这是 Git 学习中第一次要你“当裁判”——两个分支改了同一个地方,Git 无法自动决定用哪个,你必须手动裁决。我们会先故意制造一个冲突,再一步步解决它。继续在 ~/my-first-repo 操作。先确认一下当前历史形态(你的哈希值会不同):

bash
cd ~/my-first-repo
git log --oneline --graph --all

确保你在 master 分支,并且工作区是干净的:

bash
git switch master
git status

(应该显示 nothing to commit, working tree clean

冲突是如何发生的

冲突并非 Git 出错,而是两个分支修改了同一个文件的同一区域,Git 无法判断该保留哪个版本,于是把决定权交给你。

假设你和队友都发现 hello.txt 的第三行 “learning diff” 不够好,你们各自在分支里做了不同修改,现在要合并。

第一步:创建两个分支,各自修改同一行

  1. 创建并切换到 branch-A,修改第三行:
bash
git switch -c branch-A

简单起见,我们重写整个文件,确保第三行不同:

bash
echo -e "Hello, Git!\nGit is fun!\nA's change: diff is powerful" > hello.txt

-e\n 转义,但 Ubuntu 默认的 echo 可能不支持,可以改用 printf 或直接 cat <<EOF。这里写一个稳妥的方式用 heredoc):

bash
cat > hello.txt << 'EOF'
Hello, Git!
Git is fun!
A's change: diff is powerful
Author: GitLearner
Sign: Best regards
EOF

提交:

bash
git add hello.txt
git commit -m "branch-A: 修改第三行"
  1. 切回 master,创建 branch-B,同样修改第三行,但内容不同:
bash
git switch master
git switch -c branch-B

修改文件:

bash
cat > hello.txt << 'EOF'
Hello, Git!
Git is fun!
B's change: diff is easy
Author: GitLearner
Sign: Best regards
EOF

提交:

bash
git add hello.txt
git commit -m "branch-B: 修改第三行"

现在两个分支在 “第三行” 产生了分歧。图形化看看:

bash
git log --oneline --graph --all

会看到从 master 分出两个叉。

合并冲突

我们尝试把 branch-B 合并到 branch-A。冲突通常发生在你要合并时,所以先切换到 接收合并的分支(这里选 branch-A):

bash
git switch branch-A
git merge branch-B

终端会立刻显示:

bash
Auto-merging hello.txt
CONFLICT (content): Merge conflict in hello.txt
Automatic merge failed; fix conflicts and then commit the result.

这就是冲突通知。意思是:hello.txt 文件里,两个分支对同一部分有不同修改,Git 无能为力,你来解决。

查看冲突状态

运行 git status,你会看到:

bash
On branch branch-A
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   hello.txt

“both modified” 告诉你哪些文件冲突了。此时 Git 处于 合并中间状态,hello.txt 里被写入了冲突标记。

手动解决冲突

打开 hello.txt 看看里面变成什么样了:

bash
cat hello.txt

内容类似:

bash
Hello, Git!
Git is fun!
<<<<<<< HEAD
A's change: diff is powerful
=======
B's change: diff is easy
>>>>>>> branch-B
Author: GitLearner
Sign: Best regards

解释:

  • <<<<<<< HEAD======= 之间:你当前所在分支(这里 branch-A)的内容。
  • =======>>>>>>> branch-B 之间:被合并进来的分支(branch-B)的内容。

这两个版本同时存在,你必须决定:保留 A 的、保留 B 的、或者组合成一个新版本。现在你当裁判:假设我们决定综合一下,改成 "Both: diff is powerful and easy"。用编辑器修改文件。我们直接用命令行方式重写文件:

bash
cat > hello.txt << 'EOF'
Hello, Git!
Git is fun!
Both: diff is powerful and easy
Author: GitLearner
Sign: Best regards
EOF

注意:必须把 <<<<<<<=======>>>>>>> 这些标记全部删掉,并留下最终想要的内容。

标记为已解决、完成合并提交

冲突解决完后,你需要告诉 Git:“这个文件我处理好了”。将修改后的文件加入暂存区:

bash
git add hello.txt

再查看状态:

bash
git status

输出会变成:

bash
On branch branch-A
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

意思是所有冲突都解决了,但合并过程还没完成,你还需要一个提交来结束合并。现在提交:

bash
git commit -m "合并 branch-B:综合第三行修改"

这个提交会自动完成合并流程。完成后,git log --oneline --graph 会看到一个新的合并提交,将两个分支重新连在一起。

实用技巧

  1. 中止合并——git merge --abort

如果你在解决冲突的过程中慌了,比如发现搞错了分支,想回到冲突前干净的状态,用:

bash
git merge --abort

这会让分支回到执行 git merge 之前的状态,所有冲突标记消失,工作区干净。非常安全。我们不妨现在就试试:先重置一下场景(重新制造冲突),再中止。(如果你已经解决了上一个冲突并提交了,那可以先撤销最后一次合并提交来回退,但不推荐初学者这样做。我们换个思路,用 branch-C 再做一次演示。)不过现在你在 branch-A 上已经完成了合并,直接创建一个新分支演示即可。创建 branch-Cmaster 出发(确保没有冲突历史):

bash
git switch master
git switch -c branch-C
# 修改同一行造成冲突(简单复制之前操作)
cat > hello.txt << 'EOF'
Hello, Git!
Git is fun!
C's proposal: diff is magical
Author: GitLearner
Sign: Best regards
EOF
git add hello.txt
git commit -m "branch-C: 修改第三行"

再创建 branch-D

bash
git switch master
git switch -c branch-D
cat > hello.txt << 'EOF'
Hello, Git!
Git is fun!
D's proposal: diff is straightforward
Author: GitLearner
Sign: Best regards
EOF
git add hello.txt
git commit -m "branch-D: 修改第三行"

切回 branch-C 并合并 branch-D,触发冲突:

bash
git switch branch-C
git merge branch-D   # 冲突

现在查看状态,然后尝试中止:

bash
git merge --abort

状态回到合并前,hello.txt 恢复为 C 的版本,冲突消失。非常干净。

  1. 使用可视化合并工具

在 Ubuntu 终端里,如果安装了 meldvimdiff,你可以用 git mergetool 来解决冲突,但对初学者,手动编辑已经足够,而且能真正理解冲突结构。这里不深入。

远程仓库与 GitHub 协作

这一章你会打破“本地孤岛”,把代码上传到 GitHub,和别人共享、协作。我们会在 WSL2 的 Ubuntu 里配置 SSH 密钥,然后把之前那个 my-first-repo 推送到 GitHub。

准备工作:注册 GitHub 账号

如果你还没有 GitHub 账号,先去 GitHub 注册一个(免费),记住你的用户名和注册邮箱。

注意:这个邮箱最好和你第一章 git config 里设置的邮箱一致,这样 GitHub 才能把你的提交和你的账号关联起来。

配置 SSH 密钥

Git 和 GitHub 之间可以通过 HTTPS 或 SSH 通信,SSH 更安全且不用每次输密码。我们来配 SSH。

检查是否已有密钥,在终端输入:

bash
ls -al ~/.ssh

如果看到 id_ed25519id_ed25519.pubid_rsaid_rsa.pub,说明已经有密钥,可以跳过下面的生成部分;如果没有,就先生成。

生成新的 SSH 密钥(推荐 Ed25519)

bash
ssh-keygen -t ed25519 -C "你的邮箱@example.com"
  • -t ed25519 指定加密类型,更快更安全。
  • -C 后面是注释,一般填你的邮箱。

运行后会提示你选择存储位置,直接回车使用默认路径 ~/.ssh/id_ed25519。 接着提示输入 passphrase(密码短语),可以回车留空,也可以设一个额外的保护密码(你自己决定,留空更方便)。

启动 ssh-agent 并添加密钥

bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

这一步让代理管理你的密钥,免去重复输入(如果设了 passphrase 只输一次)。

复制公钥

bash
cat ~/.ssh/id_ed25519.pub

把屏幕输出的那一长串内容(以 ssh-ed25519 开头,以邮箱结尾)完整复制下来。

添加到 GitHub

  1. 浏览器登录 GitHub,点击右上角头像 → Settings。
  2. 左侧选择 SSH and GPG keys。
  3. 点击绿色的 New SSH key。
  4. Title 随便写,比如 “WSL2 Ubuntu”。
  5. Key 里粘贴刚才复制的公钥。
  6. 点击 Add SSH key。

验证配置是否成功:

bash
ssh -T git@github.com

如果看到 “You’ve successfully authenticated, but GitHub does not provide shell access.” 就说明 SSH 成功了。

在 GitHub 上创建一个空仓库

  1. GitHub 首页右上角点击 + → New repository。
  2. Repository name:填 my-first-repo(和本地目录同名,便于理解)。
  3. Description 可选。
  4. 不要勾选 “Add a README file”、“Add .gitignore” 或 “Choose a license”。因为我们已有本地仓库,如果勾选会导致历史冲突,初学者暂时避开。
  5. 点击 Create repository。

创建后你会看到一个页面,中间有 “…or push an existing repository from the command line” 一栏,里面有几条命令,正是我们接下来要执行的。

关联远程仓库

回到终端,确保在 my-first-repo 目录且干净:

bash
cd ~/my-first-repo
git status

我们给 GitHub 上的那个远程仓库起个简短的名字,约定俗成叫 origin(可以理解为主要远程仓库的默认称呼)。

在 GitHub 新建仓库的页面,找到 SSH 地址,形如:git@github.com:你的用户名/my-first-repo.git

添加远程:

bash
git remote add origin git@github.com:你的用户名/my-first-repo.git

(把“你的用户名”换成你自己的 GitHub 用户名)

验证是否添加成功:

bash
git remote -v

输出应类似:

bash
origin  git@github.com:你的用户名/my-first-repo.git (fetch)
origin  git@github.com:你的用户名/my-first-repo.git (push)

说明你的本地仓库已经关联了一个远程仓库,名字叫 origin,既可以推送(push)也可以抓取(fetch)。

推送本地内容到 GitHub

把本地的 master 分支推送给远程的 master 分支:

bash
git push -u origin master
  • -u--set-upstream 的缩写,会把本地 master 和远程 origin/master 绑定,以后在这个分支只需要 git push 即可。
  • 因为你是第一次推送,GitHub 那边是空的,所以推送成功会显示类似:
bash
Enumerating objects: 9, done.
...
To github.com:你的用户名/my-first-repo.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

现在去 GitHub 刷新你的仓库页面,hello.txtreadme.md 和历史提交都出现了

从远程获取更新

想象你有一台电脑在办公室,一台在家,或者队友向远程仓库推送了新提交,你需要把这些更新拉取到本地。

模拟远程更新:我们先在 GitHub 上直接编辑文件。

  1. 在 GitHub 仓库页面,点击 readme.md 文件。
  2. 点击右上角的铅笔图标(Edit this file)。
  3. 在文件里添加一行:## 远程协作练习
  4. 页面下方,“Commit changes” 部分,填写提交信息,比如 “通过 GitHub 网页更新 README”。
  5. 选择 “Commit directly to the master branch”。
  6. 点击 Commit changes。

现在远程仓库的 master 比你的本地多了一个提交。

拉取到本地

回到终端,确保你在本地 master 分支:

bash
git switch master
git pull

你会看到类似:

bash
remote: Enumerating objects: ...
...
Updating a1b2c3d..f6g7h8i
Fast-forward
 readme.md | 2 ++
 1 file changed, 2 insertions(+)

git pull 其实是 git fetch(获取远程数据)和 git merge(合并到当前分支)的组合。现在本地 readme.md 文件里已经有你通过网页添加的那句话了。

克隆一个仓库

如果你想在新地方完全复制一个远程仓库(比如你的另一台电脑,或者当你的本地完全乱掉想重新开始),用 git clone

为了演示,我们回到用户主目录,克隆一份我们的远程仓库到一个叫 my-first-repo-clone 的目录:

bash
cd ~
git clone git@github.com:你的用户名/my-first-repo.git my-first-repo-clone

执行后,Git 会把远程仓库的所有历史、分支都下载下来,并自动给它起名为 origin。进入这个克隆目录看看:

bash
cd ~
cd my-first-repo-clone
git log --oneline

你会发现历史记录和原来一模一样。这就是“克隆”。

历史整理与工作流技巧

这一章你会掌握四个工作利器:临时储藏现场(stash)、整理提交历史(rebase)、精准摘取提交(cherry-pick)、标记重要版本(tag)。

先在 ~/my-first-repo 里准备干净的环境,并拉取最新状态(如果有远程更新):

bash
cd ~/my-first-repo
git switch master
git pull
git status

临时暂停

想象你正在 master 上改一个 Bug,才改了一半,突然被叫去处理紧急任务。但你不想提交这个半成品,又需要切换分支。

制造一个半成品工作区

修改 hello.txt,随便加一行(但不提交):

bash
echo "WIP: stash demo line" >> hello.txt

查看状态,工作区是脏的(modified)。现在突然要切到其他分支,Git 会阻止或让你带着修改切走(如果有冲突可能切不过去)。优雅的做法是把工作区“储藏”起来。

储藏修改

bash
git stash

执行后,用 git status 查看——工作区干净了!刚才的修改消失了。再用 cat hello.txt 确认,文件回到了上次提交的状态。储藏的内容被 Git 存到了一个临时区域,可以随时取出。

查看储藏列表

bash
git stash list

会看到类似:

bash
stash@{0}: WIP on master: xxxxx 最近一次提交信息

恢复储藏

使用脚本永久激活IDM
GitHub学生认证(白嫖GitHub Copilot)
Valaxy v0.28.4 驱动|主题-Yunv0.28.4
本站总访问量
本站访客数 人次
本站已摇摇晃晃运行 0 天0 小时0 分0 秒