3、创建仓库:git init,git clone,工作区、暂存区、仓库
今天咱们来聊聊仓库创建这件事。说白了,Git 仓库就是你版本控制的「大本营」。没有仓库,你那些代码就只是一堆散装文件,哪天手一抖删了,哭都来不及。
我记得刚带团队那会儿,有个新同事上来就git init,然后在根目录下猛写代码,结果项目越来越大,分支管理一团乱。后来我才意识到——仓库怎么创建,其实藏着不少学问。
3.1 两种创建方式:git init 与 git clone
Git 提供了两条路子让你拿到仓库:从头建一个,或者从别处克隆一个。适用场景完全不同,我列个表帮你区分清楚。
| 命令 | 场景 | 初始化状态 | 典型使用 |
|---|---|---|---|
git init |
本地新建项目,还没有远程仓库 | 生成空的 .git 目录,无任何提交 | 你准备写新项目,想先搞个版本控制 |
git clone |
从远程仓库复制已有项目到本地 | 自动拉取所有历史,并设置好远程跟踪分支 | 加入团队项目或拉取开源代码 |
3.1.1 git init 详解
在你项目根目录敲下这行命令,Git 就会在当前文件夹里创建一个叫 .git 的隐藏目录。这个目录里装着整个版本库的全部元数据——提交历史、分支、配置、钩子脚本等等。你所有的工作文件都在外面,彼此不打架。
cd my-project
git init
# 输出:Initialized empty Git repository in /path/to/my-project/.git/
如果你想让仓库的名字和文件夹名不同,或者想指定远程仓库别名,可以用 --initial-branch 参数(Git 2.28+)来设置默认分支名。我个人习惯用 main 而不是 master,避免一些不必要的政治正确争议。
git init --initial-branch=main
嗯,这里要注意:git init 只是在本地新建了一个空仓库,你还没有任何提交。要开始记录版本,你得先 git add 再 git commit。
3.1.2 git clone 详解
当你想参与别人的项目,或者从公司 GitLab 拉取代码时,用 git clone。它会自动帮你做几件事:
- 创建与远程仓库同名的本地文件夹
- 初始化本地仓库
- 把远程所有分支、标签、提交历史都拉下来
- 自动设置
origin为远程别名 - 将当前工作区切换到默认分支(通常是 main 或 master)
git clone https://github.com/example/some-repo.git
cd some-repo
git branch -a # 查看所有分支,包括远程分支
我曾经遇到过一个问题:公司内网用 HTTPS 克隆超大的仓库时总是断连。后来改用 SSH 密钥认证,配合 --depth 1 只拉最新历史,速度快了一倍不止。你想想看,如果只是要看最新代码,没必要把整个项目几万次提交都拖下来吧?
git clone --depth 1 git@github.com:example/some-repo.git
这叫「浅克隆」,适合 CI 构建或临时查看。但如果你要参与开发并推代码,还是老老实实用完整克隆。
3.2 三个核心区域:工作区、暂存区、仓库
这是 Git 最基础但也最容易混淆的概念。很多人学 Git 甚至会把暂存区忽略掉,直接 git commit -a 一带而过。其实理解这三个区域,能帮你避开很多坑。
我画了张图,你看一眼就明白了。
工作区就是你磁盘上能看到的所有文件。你在这里写代码、改代码、删文件。
暂存区(也叫索引区)是一个中间缓存。你 git add 之后,修改就会进入暂存区。为什么要有这一步?因为有时候你改了很多文件,但只想把其中一部分提交到一个版本里。比如你修了 bug 又顺手改了个配置,你想分开 commit。利用暂存区就能精确选择哪些改动进这一次提交。
仓库就是 .git 目录里的那个数据库,保存着所有已经提交的版本快照。当你 git commit,暂存区的内容会被打包成一个新的提交,永久记录到仓库里。
关键区别:
- 工作区文件可以随时修改,Git 不管。
- 暂存区是「即将被记录」的候选名单。
- 仓库里的提交一旦生成,原则上不该被修改(除非你用到
git rebase等重写历史的命令,但那是另一个故事)。
3.3 实操演示:从 init 到第一次提交
为了让你更直观地感受这三个区域,我带你走一遍完整流程。假设我们要创建一个叫 learn-git 的项目。
步骤 1:创建本地仓库
mkdir learn-git
cd learn-git
git init
执行后,你会发现一个新文件夹 .git。用 ls -la 可以看见,但一般不用手动碰它。
步骤 2:在工作区创建文件
echo "# Learn Git" > README.md
echo "print('hello')" > hello.py
此时工作区多了两个文件。但 Git 还没跟踪它们。你可以用 git status 看看状态。
git status
# 输出显示 Untracked files:
# README.md
# hello.py
步骤 3:将文件添加进暂存区
git add README.md hello.py
git status
# 输出显示 Changes to be committed:
# new file: README.md
# new file: hello.py
现在这两个文件已经躺在暂存区里了。你可以随时用 git add 继续添加更多修改,或者在 commit 前用 git reset HEAD 把它从暂存区移出来。
步骤 4:提交到仓库
git commit -m "Initialize project with README and hello script"
提交成功后,你会在仓库里留下第一个永久记录。用 git log 可以看到这次提交的唯一哈希值。
commit 1a2b3c4d5e6f7g8h9i0j...
Author: Your Name <you@example.com>
Date: Mon Mar 31 14:00:00 2025 +0800
Initialize project with README and hello script
3.4 避坑指南
我曾经犯过的错:
- 直接在托管平台(如 GitHub)上创建仓库,然后本地 git init 再 push,结果忘记关联远程。 解决办法:要么先在远程建仓库然后 clone,要么本地 init 后用
git remote add origin手动关联。更推荐先 clone 再开发。 - 把大文件(如 .dll、.so、.pkl)一股脑 git add,导致仓库体积爆炸。 正确做法是写
.gitignore排除编译产物。如果你已经提交了,得用git rm --cached把它们从跟踪中移除,再提交一次。 - 用
git commit -a太顺手,忘了检查暂存区内容。 有一次我提交了不该提交的临时调试代码,差点把秘钥也提交上去。从此我坚持先用git add -p交互式选块,确保每一条改动都是我想要的。
小技巧:
- 查看当前暂存区与仓库最新提交的差异:
git diff --cached - 查看工作区与暂存区的差异:
git diff - 想丢弃工作区某个文件的修改(恢复到暂存区或最后一次提交的样子):
git checkout -- <file>
3.5 本章小结
创建仓库有两种方式:git init 适合全新项目,git clone 适合从已有远程仓库出发。不管是哪种,背后都离不开工作区、暂存区、仓库这三个基本区域。
- 工作区是你看到的实际文件。
- 暂存区是 commit 前的「中转站」。
- 仓库是保存所有版本历史的地方。
理解了这三个区域,你就能像玩积木一样灵活控制每次提交的颗粒度。记住,Git 不会对你工作区的修改做任何保护——只有当你主动 add + commit 后,版本才会被安全地存起来。
下次遇到奇怪的状态(比如 git status 显示 untracked、modified、staged 混在一起),就用这张图去对照,基本都能找到答案。