教程

Git 仓库:如何用 git init 创建并连接 remote

更新于: · Skillaria.Top

Git 仓库就是项目文件夹加上隐藏的 .git 目录,其中保存了全部历史、分支和设置。可以用 git init 在项目文件夹中创建仓库,也可以用 git clone 下载现成的仓库。远程仓库通过 git remote add origin 地址 连接。

Git 仓库就是一个由 Git 跟踪修改的项目。它在物理上是普通的项目文件夹,外加一个隐藏的 .git 目录,所有历史——提交、分支、标签和设置——都保存在那里。删除 .git,剩下的只是没有任何版本历史的文件。

仓库由哪些部分组成

使用 Git 时,需要记住三个区域,修改会在它们之间流动:

  • 工作目录(working tree):你看到并编辑的文件;
  • 暂存区(staging area,即 index):下一次提交的草稿,修改通过 git add 进入这里;
  • 历史:.git 中的提交数据库,修改通过 git commit 进入这里。

严格来说,仓库本身就是 .git 的内容。工作目录只是 Git 从历史中取出的一份“展开”的版本。

如何用 git init 创建仓库

进入项目文件夹,执行一条命令:

cd ~/projects/my-app
git init
Initialized empty Git repository in /home/user/projects/my-app/.git/

可以在空文件夹中创建仓库,也可以在已经有文件的文件夹中创建。后一种情况不会丢失任何内容:现有文件会变成未跟踪(untracked)状态,直到你用 git add 添加它们。

该命令的几个常用变体:

# 创建文件夹并同时在其中创建仓库
git init my-app

# 指定第一个分支的名称(否则默认为 master 或设置中的值)
git init -b main

# 让 main 成为所有新仓库的默认分支
git config --global init.defaultBranch main

第一次提交

没有任何提交的空仓库几乎没有用处。执行 git init 之后,通常这样操作:

git config --global user.name "Ivan Petrov"
git config --global user.email "ivan@example.com"

git status
git add .
git commit -m "Initial project structure"

用户名和邮箱只需在电脑上设置一次,它们会被写入每一次提交。没有设置的话,Git 会拒绝提交,并要求你先表明身份。

马上添加 .gitignore

在第一次 git add . 之前,先创建 .gitignore,列出不应进入仓库的内容:依赖、构建产物、机密信息、IDE 文件。

node_modules/
dist/
.env
.idea/
.vscode/
*.log
__pycache__/

如果文件已经被提交,.gitignore 并不会把它移除。需要停止跟踪它,同时保留磁盘上的文件:git rm --cached .env,然后提交。

.git 文件夹里有什么

日常工作中不需要进入这个目录,但了解其结构能解答很多疑问:

条目保存的内容
objects/压缩后的对象:文件内容(blob)、目录结构(tree)、提交
refs/heads/分支:内容为最后一次提交哈希的文件
refs/tags/标签
HEAD指向当前分支的指针,例如 ref: refs/heads/main
config该仓库的设置,包括 remote 列表
index暂存区的状态
hooks/在事件(如 pre-commit、pre-push)发生时运行的脚本

由此可以得出重要结论:Git 中的分支只是一个包含单个哈希的小文件。因此创建分支是瞬间完成的,而且不占多少空间。

如何确认某个文件夹是仓库

git status
# 或者更精确地
git rev-parse --is-inside-work-tree

如果不在仓库中,会得到 fatal: not a git repository (or any of the parent directories): .git。注意其中的 “parent directories”:Git 会向上逐级查找 .git。如果不小心在用户主目录中执行了 git init,那么整个主目录都会变成仓库——此时需要删除那个 .git 文件夹。

本地仓库与远程仓库

通过 git init 创建的仓库只存在于你的电脑上。要与他人共享代码并保留备份,需要连接一个远程仓库(remote),即服务器上的副本:GitHub、GitLab、Bitbucket,或你自己的 Git 服务器。

从 Git 的角度看,远程仓库并不是“主”仓库:每个副本都是完整的,并且包含全部历史。只有团队的约定才使它成为中心。

git remote:连接远程仓库

remote 是服务器地址的简称。按惯例,主 remote 的名称是 origin。

# 添加 remote
git remote add origin git@github.com:username/my-app.git

# 查看 remote 及其地址
git remote -v
origin  git@github.com:username/my-app.git (fetch)
origin  git@github.com:username/my-app.git (push)

然后推送分支,并建立与远程分支的关联:

git push -u origin main

git remote 的常用命令

命令作用
git remote -v列出 remote 及其地址
git remote add <名称> <url>添加新的远程仓库
git remote set-url origin <url>修改地址,例如从 HTTPS 改为 SSH
git remote rename origin old重命名 remote
git remote remove old删除 remote(不影响服务器本身)
git remote show origin详细信息:分支、跟踪关系、落后情况

地址格式

  • https://github.com/user/repo.git:HTTPS 方式,任何地方都可用,写入时需要令牌;
  • git@github.com:user/repo.git:SSH 方式,需要密钥,配置好之后无需输入密码;
  • /srv/git/repo.git 或 file:///srv/git/repo.git:本地路径,适合实验。

常见错误

“error: remote origin already exists”。 同名 remote 已经存在。如果要修改地址,使用 git remote set-url origin <url>,而不是再次执行 add。

“failed to push some refs” / “Updates were rejected”。 服务器上有你本地没有的提交,通常是在网站上创建仓库时自动生成的 README。执行 git pull --rebase origin main,然后再次推送。如果两段历史完全无关,Git 会提示“refusing to merge unrelated histories”,此时 git pull 需要加上 --allow-unrelated-histories。更省事的做法是:在网站上创建完全空白的仓库。

“src refspec main does not match any”。 你要推送的分支不存在:要么还没有任何提交,要么分支名为 master。用 git branch 检查。

自己的 Git 服务器:裸仓库(bare)

GitHub 并不是必需的。任何你能通过 SSH 访问的机器都可以作为远程仓库。为此,在服务器上创建一个“裸”(bare)仓库——没有工作目录,只有 .git 的内容:

# 在服务器上
ssh user@server
git init --bare /srv/git/my-app.git

# 在自己的电脑上
git remote add origin user@server:/srv/git/my-app.git
git push -u origin main

要让三个人共同使用这样的服务器,只需给同事 SSH 访问权限,并为仓库文件夹设置一个有写入权限的共享组。如果需要按分支或项目划分权限,这样就不够用了,那时需要完整的 Git 托管服务。

不能在裸仓库中“进去修改文件”——它只用于通过 push 和 fetch 交换数据。所有 Git 托管平台的仓库都是这样工作的。如果需要网页界面、评审和任务管理,可以部署自托管方案,例如 GitLab、Gitea 或 Forgejo。

跟踪分支:本地仓库如何看到服务器

连接 remote 并首次执行 git fetch 或 git push 之后,仓库中会出现形如 origin/main 的远程分支。它们并不是服务器上的分支,而是你上次同步时所见服务器状态的本地快照。只有执行 fetch、pull 和 push 时才会更新。

三个交换命令的区别如下:

命令改变的内容
git fetch更新 origin/*,不改动你的分支和文件
git pullfetch 加上把 origin/main 合并到当前分支
git push发送你的提交,并更新服务器上的分支

查看你的分支比服务器超前或落后多少:

git fetch
git status -sb
## main...origin/main [ahead 2, behind 1]

这表示你有两个服务器上没有的提交,同时服务器上还有一个你没有的提交。在 push 之前,需要先拉取那个提交。

在第一次 push 时加上 -u,即可设置本地分支与远程分支的关联(upstream)。如果忘了,可以单独设置:git branch --set-upstream-to=origin/main。使用 git branch -vv 查看所有关联。

多个仓库:单体仓库还是每个项目一个仓库

新手常问要创建多少个 Git 仓库。一个简单的规则:每个可以独立开发和发布的单元对应一个仓库。练习项目、个人项目和各个独立服务应当分开存放。不要为整个“我的项目”文件夹建一个仓库:历史会混在一起,要单独展示某个项目到作品集也会变得困难。

大公司有时出于统一修改和统一构建的目的,会把所有代码放在一个单体仓库(monorepo)中,但这是需要配套工具的架构决定。新手应该从“一个项目一个仓库”开始,并且不要在一个仓库中直接嵌套另一个仓库,除非使用子模块。

git init 还是 git clone

场景命令
从零开始一个新项目git init
已有没有版本控制的代码文件夹在该文件夹中执行 git init
项目已经在 GitHub 或服务器上git clone <url>
需要在自己的服务器上建立中心仓库git init --bare

执行 git clone 之后,origin remote 已经配置好,无需手动添加。

分步示例:从文件夹到 GitHub 上的仓库

  1. 创建项目文件夹,执行 git init -b main。
  2. 添加 .gitignore 和 README。
  3. 做第一次提交:git add .,然后 git commit -m "Initial commit"。
  4. 在 GitHub 上创建一个空仓库——不要勾选 README、许可证或 .gitignore。
  5. 连接它:git remote add origin <地址>。
  6. 推送代码:git push -u origin main。
  7. 之后按循环工作:修改 → git add → git commit → git push。

总结

Git 仓库就是你的项目加上包含完整历史的 .git 文件夹。用 git init 创建,用 git remote add origin 和首次 git push -u 建立与服务器的连接。远程仓库可以是 GitHub、GitLab,也可以是你自己的、包含裸仓库的 Git 服务器。创建第一个仓库、理解暂存区以及连接 remote 的实践,在 Git 课程中有讲解。

常见问题

如何删除 Git 仓库,但保留文件?

删除项目根目录下的隐藏文件夹 .git。在 Linux 和 macOS 上执行 rm -rf .git。文件会保留,但全部版本历史都会丢失。

在已经是仓库的文件夹中执行 git init 安全吗?

安全。Git 会提示 Reinitialized existing Git repository,不会改动历史,只会补充缺少的内部文件。

一个仓库可以连接多少个 remote?

任意多个。比如向自己的 fork 推送时用 origin,同步原始项目时用 upstream,开源项目通常这样工作。

仓库的设置保存在哪里?

保存在 .git/config 文件中。用户级的全局设置位于 ~/.gitconfig,通过 git config --global 修改。

裸仓库与普通仓库有什么区别?

裸仓库没有工作目录,只保存 Git 的内部数据。它作为中心仓库部署在服务器上,用于接收 push。

通过视频学习本主题

课程“Git 从零基础到胜任开发者”结合实践详细讲解了这一主题。

前往课程