Git clone 到底是什么?
本文介绍了 Git clone 的几种方式,还有一些有用的参数
我们经常使用 git clone,但大多数情况下,我们都是从一个中心化的远程仓库,比如 GitHub,GitLab 等等。但实际上,这一条命令有更简单的含义。
HTTPS
最常见的方式。
git clone https://github.com/torvalds/linux.git
SSH
通过这种方式 clone,需要在 Github 上传 SSH 公钥,才能通过鉴权。
git clone [email protected]:torvalds/linux.git
但是事实上,这里并不一定得是 github,这里其实可以是任何一个你有权通过 ssh 访问的主机,例如:
git clone [email protected]:test/.git
假设 user 的家目录里面有个 test 目录,这个目录是一个 git repo,那么这条命令就会把 user 的 ~/test clone 下来。
看看,上面两个命令有多像,所以实际上,当我们使用 SSH clone 的时候,就是通过 SSH 登录上了 github.com 这台主机。


如果你尝试使用 ssh 直接登录 github,会有下面的提示:
$ ssh [email protected]
PTY allocation request failed on channel 0
Hi <USER_NAME>! You've successfully authenticated, but GitHub does not provide shell access.
Connection to ssh.github.com closed.
本地路径
既然能通过 ssh clone,想必也可以从本地 clone 了。
git clone /path/to/repo/.git
这样就可以从本地 clone 下来。
更神奇的是,居然也可以 push,只不过会报这个错:
$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 257 bytes | 257.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: error: refusing to update checked out branch: refs/heads/main
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /path/to/repo/.git
! [remote rejected] main -> main (branch is currently checked out)
error: failed to push some refs to '/path/to/repo/.git'
这个错误是因为:正在向一个非裸仓库(non-bare repository)的当前检出分支(checked-out branch)进行推送。
如果确实有需求这样做,有两种方法:
- 创建裸仓库
- 可以把当前仓库 clone 一份
git clone --bare . ../test.git - 也可以在创建仓库的时候就直接使用裸仓库:
git init --bare /path/to/central-repo.git
- 可以把当前仓库 clone 一份
- 不要往当前检出分支推送
- 可以在 remote 里运行
git checkout --detach,分离头指针 - 也可以切换到其他分支
git switch -c temp-branch - 也可以在 push 的时候改名
git push origin main:new-branch(把本地的 main 推送到 origin 的 new-branch 上)
- 可以在 remote 里运行
总结
所以说,remote 并不一定得是一个中心化的仓库,它其实可以是任何一个位置的仓库,双方是对等的。像 git clone, git push, git pull 等等只需要两台(甚至一台)安装有 git 客户端的主机就可以了。
有用的 Git Clone 参数
这里列举一些常用的 git clone 参数。
-
设置上游的别名。当存在多个上游的时候,可以用这个办法设置别名。
# 将上游仓库命名为 upstream 而不是 origin git clone -o upstream https://github.com/otheruser/original-repo.git -
设置目标目录,而不是默认的以仓库名作为目录名。
# 将仓库克隆到 my-project 文件夹,而不是默认的 repo 文件夹 git clone https://github.com/user/repo.git my-project -
控制 clone 的深度。如果只是想把代码下载下来看看,可以使用
--depth=1。# 只克隆最近一次提交,历史记录为空 git clone --depth=1 https://github.com/vuejs/vue.git # 按照时间筛选 git clone --shallow-since="2024-01-01" https://github.com/user/repo.git # 如果想要更多历史,可以这样补救 git fetch --depth=10 # 或者这样直接获取所有的历史 git fetch --unshallow -
只克隆一个分支。可以和上面的深度结合起来。
# 只克隆 main 分支的最新代码 git clone --single-branch --branch main --depth=1 https://github.com/user/repo.git # 如果需要其他分支,也可以用下面的命令补充。 git fetch origin feature-x:feature-x
