Git简单知识

工作目录(Working Directory):在计算机文件系统中实际编辑和修改代码的地方(本机文件目录及文件)。在工作目录中,您可以对代码进行更改、新增文件或删除文件,但这些变更并不会立即被 Git 跟踪。

暂存区(Staging Area):也称为“索引(Index)”,是介于工作目录和版本库之间的中间区域。当您修改了工作目录中的文件后,您可以使用 git add 命令将这些更改添加到暂存区。暂存区中存储了您要在下一次提交中包含的更改快照。

版本库(Repository):也称为“Git 版本库”,它是保存所有项目历史记录的地方。版本库包含了您提交的快照,以及用于跟踪这些快照如何相互关联的元数据。每次使用 git commit 命令提交更改时,会在版本库中创建一个新的提交对象。

除了上面的常用词汇外,可能您还听过远程库(Git 仓库)、上游仓库(upstream),其中远程库泛指代码托管平台(可以自行搭建):Github、Gitee 等代码托管平台,而上游仓库特指 fork 的仓库。

常用命令

简单常用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 将当前目录中所有文件文件改动添加到git暂存区,也可以一次提交多个指定文件,使用空格分开
$ git add .
# 提交到版本库并备注提交信息
$ git commit -m "my first commit"

# 上面两条命令可以合并成一条
$ git commit -am 'commit msg'

# 如果第一次提交(commit但未push)的内容写的不好或者还有新的相关文件未提交,可以使用下面的命令覆盖之前一次的 commit
$ git commit --amend -m "override first commit"
# 将本地分支推送到远程分支并建立映射,如果远程不存在将自动创建
# 推送到远程仓库,如果本地和远程的分支名称相同,可以写一个分支名
# 第一个 master 是本地分支,后面的一个是远程分支
$ git push -u origin [local-branch]:[remote-branch]

# 删除远程分支 --delete 简写为 -d
$ git push origin -d [branch-name]

# 移除文件
# 从暂存区移除文件,会把工作区相应文件一并删除,回收站无法还原。如果该文件没有提交,则无法删除,可以使用 -f 选项强制删除。
$ git rm [file]
# 移除 commit 的文件,保留工作区文件;如果不加 --cached,那么暂存区和本地的文件都会被删除
$ git rm --cached [file]
# 移除 commit 的文件夹
$ git rm --cached -r [path]

clone

1
2
3
4
# 克隆远程库到本地
$ git clone [repo-url]
# 克隆指定的分支
$ git clone -b [branch-name] [repo-url]

–depth

有时候,我们可能会见到这样的命令:

1
2
# 可以简写为 -d
$ git clone --depth [num] https://github.com/user/repo.git

--depth 是 clone 命令的一个选项,用于指定克隆的历史记录的深度。num 是一个参数,由自己指定,表示只克隆最近的 num 次提交的历史记录,而不是整个仓库的完整历史记录。这可以节省时间和空间,尤其是在克隆大型仓库时会更加有用。

如果我们是为了学习和使用可以使用该选项 clone 最近的一次就可以,没有必要全部 clone,下载的速度会加快;而如果我们想要为项目添砖加瓦做贡献则推荐全部 clone。

upstream

1
2
3
4
5
6
7
8
9
10
11
# 关联上游仓库
$ git remote add upstream [upstream-repo-url]
# 取消关联上游仓库
$ git remote remove upstream
# 更新上游仓库
$ git pull upstream

# 与上游仓库建立分支映射
$ git pull --track upstream [branch-name]
# 如果已经有一个本地分支,并且想要将其设置为跟踪上游的分支
$ git branch -u upstream/[branch-name] [branch-name]

remote

1
2
3
4
5
6
7
8
9
10
# 关联远程仓库
$ git remote add origin https://github.com/user/repo.git
# 取消远程关联
$ git remote remove origin
# 更新远程关联的仓库
$ git remote set-url origin [repo-url]

# 删除/清理本地分支存在,但远程仓库中不存在的分支
# 即:清理本地和远程没有跟踪关系的分支
$ git remote prune origin

branch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 新建分支
$ git branch [new-branch-name]
# 切换到指定分支并更新工作目录
$ git switch -c [branch]
# 查看本地所有分支
$ git branch -a
# 查看远程分支
$ git branch -r
# 查看本地与远程分支的一映射关系
$ git branch -vv
# 重命名本地分支
$ git branch -m [old-branch] [new-branch]

# 删除本地分支,如果要强制删除分支,使用 -D 选项
$ git branch -d [branch]
# 删除远程分支
$ git push -d origin [branch-name]
# 也可以使用以下命令
$ git push origin :[branch-name]

log

1
2
3
4
5
6
7
8
9
10
11
12
# 提交历史
$ git log
# 图形化显示
$ git log --graph
# 单行显示、短格式、长格式 oneline, full
$ git log --pretty=oneline/full
# 单行简写
$ git log --oneline
# 图形化输出 log
$ git log --graph --oneline
# 全格式图形化输出 log
$ git log --graph --pretty=full

reset

1
2
3
4
# 撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到指定版本
$ git reset --hard 版本ID
# 回退到某个版本,但工作目录和暂存区不会受到影响
$ git reset --soft 版本库ID

stash

git stash 命令将当前未提交的修改(即,工作区的修改和暂存区的修改)先暂时储藏起来,这样当前的工作区就干净了。然后可以直接切换到其它分支进行修改。修改完成后重新切换到当前分支下通过 git stash pop 命令将之前储藏的修改取出来,继续进行新功能的开发工作。

1
2
3
4
5
6
7
# 贮藏当前的工作区文件的修改
git stash

# 切换其它分支进行开发,开发完成后再切换到当前分支

# 取出最近一次的贮藏文件
git stash pop

上面的只是简单的使用,此选项是支持多次使用的,并且可以查看列表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 第一次修改文件
# 藏储文件时附加消息
git stash save [message]

# 第二次修改文件
# 藏储文件时附加消息
git stash save [message]

# 查看列表
git stash list

# 取出最近一次的文件
git stash pop

# 取出指定index的储藏的修改到工作区中
git stash apply stash@{index}
# 将指定index的储藏从储藏记录列表中删除
git stash drop stash@{index}

submodule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# clone 时直接 clone 子模块
git clone --recurse-submodules [repo-url]

# 添加子模块
$ git submodule add [repository-url] [path]
# 初始化子模块,根据 .gitmodules 文件设置子模块的 url
# 常与 update 连用
$ git submodule init --recursive
# 更新子模块,如果没有 clone 子模块则会 clone
$ git submodule update --recursive

# init 和 update 也可以使用一个命令
$ git submodule update --init --recursive

# 查看子模块状态
$ git submodule status

–recursive 为可选项,如果存在,会同时对嵌套的子模块进行相应的操作。

更新 submodule 为最新版本

1
$ git submodule update --remote

删除 submodule

1
2
3
4
5
6
$ cd [repo]
$ git submodule deinit [submodule-path]
# 有需要的话可以使用 --force 移除
$ git rm -rf [submodule-path]
$ git commit -m "delete submodule"
$ git push

重置 submodule 地址

打开仓库下的 .gitmodules 文件,修改对应的 url 地址并保存,然后执行以下命令:

1
$ git submodule sync

此时,submodule 的信息已经更新,可以删除旧的子模块再使用 git submodule update --init --recursive 进行子模块初始化。

同时对所有子模块进行操作

1
2
3
4
5
6
$ git submodule foreach [git-cmd]

# 更新所有子模块到最新版本
$ git submodule foreach git pull origin main
# 查询所有子模块的状态
$ git submodule foreach git status

常见问题

合并不相关的历史

有时候我们可能不会直接 clone 远程仓库,而是直接在本地创建新的 git 目录,然后在此目录中添加新的文件,最后再关联远程仓库。在这个前提下,如果远程仓库中 已经存在文件,直接 pull 的时候会报错:拒绝合并不相关的历史。

1
fatal: refusing to merge unrelated histories

这时我们可以使用 --allow-unrelated-histories 选项进行强制合并(也可以按照 Git 的提示去做,应该有设置分支关联的方式。Git 的报错提示还是很不错的)。

1
git pull origin [remote-branch] --allow-unrelated-histories

22 端口被占用

如果你配置了 C:\Users\youruser\.ssh\config 文件,一般是如下配置:

C:\Users\youruser\.ssh\config
1
2
3
4
5
Host github.com
User git
Hostname github.com
Port 22
IdentityFile ~/.ssh/your_private_key

但是,如果使用本地代理或者 tun 代理,例如使用 Watt Toolkit 工具加速 Github 的访问。那么你们惊奇的发现使用 SSH 协议的 Git 仓库就都推不上去了(还包括 pull、clone 等),必须关闭代理工具才可以,这是相当麻烦的。使用的时候显示以下错误:

1
2
3
4
5
6
$ git pull
ssh: connect to host github.com port 22: Connection refused
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

然后网上查了查资料,有这样说的:

说法之一

这是 GitHub 为了应对网络限制,默认的 SSH 端口 22 可能会被一些机构或地区的防火墙封锁。因此,GitHub 提供了通过 HTTPS 端口 443 访问 Git 仓库的替代方案,这个端口通常用于 HTTPS 协议,大多数网络环境不会对它进行限制。

因此我们可以在 SSH 配置中,将端口设置为 443,实际上是让 SSH 连接通过 HTTPS 端口与 GitHub 的服务器建立连接。这样即使在默认的 22 端口被阻塞的情况下,您依然可以通过 443 端口进行正常的 Git 操作。

浪子不知,那么就把 Git 改为 443 端口代理转发试试看啦!结果还真可以!

就是 hostname 需要 修改 一下,下面两种方式任选一种配置即可。

方式一:

C:\Users\youruser\.ssh\config
1
2
3
4
5
Host github.com
User git
Hostname ssh.github.com
Port 443
IdentityFile ~/.ssh/your_private_key

方式二:

~/.ssh/config
1
2
3
4
5
6
7
8
9
Host github.com
# 指定 SSH 使用 443 端口
Port 443
# HostName 是代码托管平台的域名,例如:code.aliyun.com, github.com, gitee.come 等
HostName ssh.github.com
# 设置用户身份认证方式,这里当然使用 公/私钥 的方式
PreferredAuthentications publickey
# 指定公钥对应的 私钥 路径
IdentityFile ~/.ssh/github_id_rsa

这样配置之后可以 ssh -T git@github.com 测试一下,需要输入的话输入 yes 即可。

如果还是不行,就尝试一下网络上的普遍方式,设置代理,让 Git 直接走代理,Windows 的话可能较为麻烦,浪子未使用。

HTTP/HTTPS 代理设置

<proxy-url> 替换为您的代理服务器地址及端口

1
2
git config --global http.proxy http://<proxy-user>:<proxy-password>@<proxy-url>
git config --global https.proxy https://<proxy-user>:<proxy-password>@<proxy-url>

如果不需要身份验证,则直接使用代理服务器地址:

1
2
git config --global http.proxy http://<proxy-url>:<proxy-port>
git config --global https.proxy https://<proxy-url>:<proxy-port>

取消代理:

1
2
git config --global --unset http.proxy
git config --global --unset https.proxy

SSH 代理设置

对于 SSH,Git 不直接支持 HTTP(S) 代理,但可以通过系统级的 SOCKS 代理转发。假设您有一个 SOCKS 代理运行在本地 1080 端口,可以在终端中启动 SSH 的动态端口转发:

1
2
3
4
ssh -D 1080 <your-socks-proxy-server>

# 设置环境变量 GIT_SSH_COMMAND 来启用 socks 代理转发:
git config --global core.sshCommand 'ssh -o ProxyCommand="nc -X 5 -x localhost:1080 %h %p"'

1080 是 SOCKS 服务的默认端口。

Windows 系统中没有 nc 命令,可以去 Nmap 官网下载适用于 Windows 的版本安装。然后使用以下命令设置:

1
git config --global core.sshCommand 'ssh -o ProxyCommand="ncat --proxy-type socks5 --proxy localhost:1080 %h %p"'

另外,Windows 系统下也可以尝试使用 PuTTY 的 plink.exe 工具代替 ssh 实现类似功能:

1
git config --global core.sshCommand '"C:/Program Files (x86)/PuTTY/plink.exe" -agent -proxycmd "ncat --proxy-type socks5 --proxy localhost:1080 %host %port"'

plink 的路径需要修改为少侠本地的路径

SSL 验证 sslverify

http.sslverify:通过 HTTP/HTTPS 访问 Git 远程仓库时,如果没有配置或是服务器上的 SSL 证书未经过第三方机构认证,Git就会报错。未知的证书意味着可能存在很大的风险。

以下报错在使用 HTTP 地址时比较常见,所以更加推荐使用 SSH 或者远程托管平台生成的 Token 等认证方式。当然,有时候我们不得不使用 HTTP,那么也是有解决办法的。

1
SSL certificate problem: unable to get local issuer certificate

如果对该仓库足够信任,我们可以在当前报错的 Git 仓库中使用以下命令关闭 SSL 验证(极不推荐 --global 全局配置选项):

1
git config http.sslverify false

上面这种方式对于 clone 时报错时是无效的,但是还有一种可能(这种可能性较小),因为 Windows 的 Git 默认使用 Linux 的后端加密方式,这种方式在 Windows 中可能有问题导致命令无法完成,在 Git 2.14 之后的版本中,可以使用以下命令使用内置的 Windows 网络安全层。

1
git config --global http.sslbackend schannel

https://github.com/desktop/desktop/issues/9293


本站由 江湖浪子 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。