526 lines
13 KiB
Markdown
526 lines
13 KiB
Markdown
# Git 使用说明
|
||
|
||
## 1. 初始配置
|
||
|
||
### 1.1. Git 初始配置
|
||
|
||
在使用 Git 前需要配置好用户名和电子邮件信息,Git 需要使用这些配置信息用于提交代码。在 Git 命令行下,可以使用如下命令设置用户名和电子邮件信息:
|
||
|
||
```bash
|
||
git config --global user.name "Your name"
|
||
git config --global user.email "Your email"
|
||
```
|
||
|
||
查看当前配置的用户名和电子邮件信息命令如下:
|
||
|
||
```bash
|
||
git config --global user.name
|
||
git config --global user.email
|
||
```
|
||
|
||
git 访问某些 https 连接会出现 SSL 认证错误,此时可通过全局配置关闭 SSL 认证:
|
||
|
||
```bash
|
||
git config --global http.sslVerify "false"
|
||
```
|
||
|
||
克隆比较大的项目时容易出现 RPC failed,通过将 postBuffer 设置大些以解决此问题:
|
||
|
||
```bash
|
||
git config --global http.postBuffer 524288000
|
||
```
|
||
|
||
### 1.2. Git 与 SSH
|
||
|
||
如果想访问远程 Git 服务器,则最好通过 SSH 方式。这需要先生成 RSA 密钥,然后将公钥部署到远程服务器上即可。生成 RSA 密钥可使用 OpenSSH,命令如下(Windows 下该命令位于 /\<git 安装目录\>/usr/bin/ 下,可使用 Git Bash 直接访问):
|
||
|
||
```bash
|
||
ssh-keygen
|
||
```
|
||
|
||
之后一路回车,生成文件为:
|
||
|
||
```bash
|
||
<Usr>/.ssh/id_rsa
|
||
<Usr>/.ssh/id_rsa.pub
|
||
```
|
||
|
||
其中 id_rsa 为私钥,id_rsa.pub 为公钥,将公钥中的内容拷贝到远程服务器中对应的设置项中即可。
|
||
|
||
TortoiseGit 需要额外修改 Settings->Network->SSH 为 C:\Windows\System32\OpenSSH\ssh.exe 才可以通过 OpenSSH 密钥来访问服务器。否则默认使用 PuTTY 格式密钥。
|
||
|
||
## 2. 创建仓库
|
||
|
||
软件版本管理依赖于软件仓库的概念,一个软件仓库包容了要进行版本管理的源码和 Release 发布等内容。
|
||
|
||
在要进行版本管理的目录下键入:
|
||
|
||
```bash
|
||
git init
|
||
```
|
||
|
||
命令,可完成软件版本仓库的创建操作,在创建完软件仓库后,该目录下会生成一个名为“.git”的隐藏文件夹,该文件夹下保存了软件的历史和分支等版本信息,通常不需要直接操作该目录。
|
||
|
||
## 3. 添加跟踪文件
|
||
|
||
版本仓库所在文件夹下的文件并不是全部都会被 git 跟踪和管理。如果需要将该文件夹下将某个文件纳入到版本管理中,则需要通过 add 命令添加到 git 仓库中进行跟踪:
|
||
|
||
```bash
|
||
git add <file name>
|
||
```
|
||
|
||
例如:
|
||
|
||
```bash
|
||
git add main.c
|
||
```
|
||
|
||
## 4. 取消跟踪文件
|
||
|
||
如果对某个文件取消跟踪,但还需要保留本地文件,则使用如下命令:
|
||
|
||
```bash
|
||
git rm --cached <file name>
|
||
```
|
||
|
||
如果取消对某个文件的版本管理,并且要删除该文件,则使用如下命令:
|
||
|
||
```bash
|
||
git rm --f <file name>
|
||
```
|
||
|
||
## 5. Clone 仓库
|
||
|
||
更多的时候,不需要手动创建 git 仓库。git 仓库很可能已经存在于远端服务器或别人的计算机中,这时候我们只需要将其 clone 到本地即可:
|
||
|
||
```bash
|
||
git clone <repository url>
|
||
```
|
||
|
||
例如:
|
||
|
||
```bash
|
||
git clone https://192.168.1.8/path/repo.git
|
||
```
|
||
|
||
git 支持 http、https、ssh 格式的 URL 访问。
|
||
|
||
## 6. 提交变更
|
||
|
||
在修改代码或相关文件后,需要先将变更缓存到本地,这一步被称作 commit。带签名的提交命令如下:
|
||
|
||
```bash
|
||
git add .
|
||
git commit -s -m <message>
|
||
```
|
||
|
||
如果想对上次提交进行修改,或将本次提交与上次提交合并,可为 commit 增加 amend 参数,如下:
|
||
|
||
```bash
|
||
git commit --amend
|
||
```
|
||
|
||
之后可通过交互界面进行编辑和修改。
|
||
|
||
## 7. 时光穿梭
|
||
|
||
如果文件尚未 stash,可使用 checkout 命令撤回修改:
|
||
|
||
```bash
|
||
git checkout -- <file>
|
||
```
|
||
|
||
如果文件已 stash 但是没有 commit,可使用 reset 命令撤回修改:
|
||
|
||
```bash
|
||
git reset HEAD <file>
|
||
```
|
||
|
||
如果文件已经 commit,可使用下列命令
|
||
|
||
```bash
|
||
git reset --soft <commit id>
|
||
git reset --hard <commit id>
|
||
git reset --hard HEAD~10
|
||
git revert <commit id>
|
||
```
|
||
|
||
注意 soft 与 hard 的区别主要在于 hard 不保留工作区中的内容,但是 soft 保留工作区中的内容。而 reset 与 revert 的区别在于 revert 是放弃指定提交的修改,但是会生成一次新的提交,需要填写提交注释,以前的历史记录都在,而reset是指将HEAD指针指到指定提交,历史记录中不会出现放弃的提交记录。
|
||
|
||
## 8. 分支管理
|
||
|
||
通过以下命令创建新的本地分支:
|
||
|
||
```bash
|
||
git branch <branch>
|
||
```
|
||
|
||
还可以通过以下命令查看分支情况:
|
||
|
||
```bash
|
||
git branch
|
||
git branch -a
|
||
```
|
||
|
||
使用下列命令切换到对应分支:
|
||
|
||
```bash
|
||
git checkout <branch>
|
||
```
|
||
|
||
推送本地指定分支到远程指定分支,如果远程分支不存在则创建:
|
||
|
||
```bash
|
||
git push <repository> <local branch>:<remote branch>
|
||
```
|
||
|
||
如,推送本地的 new 分支与 \<repository\> 主机的 master 分支合并:
|
||
|
||
```bash
|
||
git push <repository> new:master
|
||
```
|
||
|
||
从远程分支更新本地分支:
|
||
|
||
```bash
|
||
git pull <repository> <remote branch>:<local branch>
|
||
```
|
||
|
||
如,要取回 \<repository\> 主机的 new 分支,与本地的 master 分支合并:
|
||
|
||
```bash
|
||
git pull <repository> new:master
|
||
```
|
||
|
||
如果远程仓库有所变更,但本地代码没有更新就进行了 commit,在使用 git pull 的时候会进行自动 merge,如果有冲突则需要手动解决。
|
||
|
||
删除某本地分支的命令为:
|
||
|
||
```bash
|
||
git branch -d <branch>
|
||
```
|
||
|
||
删除某远程分支的命令为
|
||
|
||
```bash
|
||
git push <repository> --delete <branch>
|
||
```
|
||
|
||
将某个分支与当前分支合并的命令为:
|
||
|
||
```bash
|
||
# merge 谋 branch 到当前分支.
|
||
git merge <branch>
|
||
```
|
||
|
||
以下命令为本地分支指定一个与之对应的远程分支:
|
||
|
||
```bash
|
||
git branch --set-upstream-to=<repository>/<remote branch> <local branch>
|
||
```
|
||
|
||
删除远程分支命令为:
|
||
|
||
```bash
|
||
git push <repository> --delete <branch name>
|
||
```
|
||
|
||
如果谋远程分支已经删除,需要同步到本地,可使用以下命令:
|
||
|
||
```bash
|
||
git remote prune <repository>
|
||
```
|
||
|
||
## 9. 查看历史
|
||
|
||
版本管理提供的最主要的功能之一便是历史追溯,可以查看每一次变更的内容,相关提交的信息等。通过下列命令实现:
|
||
|
||
```bash
|
||
# 显示提交日志概要
|
||
git log [path]
|
||
# 显示提交日志,包括变更的文件
|
||
git whatchanged [path]
|
||
# 可通过 git log 获取要查看的提交及其 commit id,然后通过 git show 显示此次提交的详细信息
|
||
git show <commit id>
|
||
```
|
||
|
||
## 10. 内容比较
|
||
|
||
使用
|
||
|
||
```bash
|
||
git diff <from> <to>
|
||
```
|
||
|
||
命令可比较任意两组内容,例如:
|
||
|
||
```bash
|
||
# 比较谋更改的文件/文件夹与当前分支上次提交内容的差异
|
||
git diff <file/folder>
|
||
# 比较两个分支 或 两个分支的谋文件/文件夹
|
||
git diff <branch 0> <branch 1> [file/folder]
|
||
# 比较当前分支下两次提交 或 两次提交的谋文件/文件夹
|
||
git diff <commit id 0> <commit id 1> [file/folder]
|
||
```
|
||
|
||
## 11. Tag 管理
|
||
|
||
可以通过:
|
||
|
||
```bash
|
||
git tag
|
||
```
|
||
|
||
命令列出当前仓库中的所有标签,创建一个带附注的的标签则可以使用以下命令实现:
|
||
|
||
```bash
|
||
git tag -a <tag name> -m <message>
|
||
```
|
||
|
||
还可以使用:
|
||
|
||
```bash
|
||
git tag <tag name>
|
||
```
|
||
|
||
创建一个轻量标签。
|
||
|
||
使用 -d 参数删除标签:
|
||
|
||
```bash
|
||
git tag -d <tag name>
|
||
```
|
||
|
||
将本地 Tag 同步到远程的命令为:
|
||
|
||
```bash
|
||
git push --tags [-f]
|
||
```
|
||
|
||
将远程 Tag 同步到本地的命令为:
|
||
|
||
```bash
|
||
git pull --tags [-f]
|
||
```
|
||
|
||
如需将远程谋 Tag fetch 到本地,则命令为:
|
||
|
||
```bash
|
||
git fetch <repository> tag <tag name>
|
||
```
|
||
|
||
删除远程 Tag 的命令为:
|
||
|
||
```bash
|
||
git push <repository> --delete tag <tag name>
|
||
```
|
||
|
||
如果谋远程 Tab 已经删除,需要同步到本地,可使用以下命令:
|
||
|
||
```bash
|
||
git remote prune <repository>
|
||
```
|
||
|
||
## 12. Repository 管理
|
||
|
||
```bash
|
||
# 查看远程 repository 设置情况
|
||
git remote -v
|
||
# 添加 repository
|
||
git remote add <repository> <utl>
|
||
# 删除 repository
|
||
git remote rm <repository>
|
||
# 修改 repository 的 url
|
||
git remote set-url <repository> <utl>
|
||
```
|
||
|
||
## 13. Rebase
|
||
|
||
由于合并分支,或从远程仓库中更新代码产生了额外的 merge 节点,此时可通过 rebase 命令消除这些额外的 merge 节点,使 git 历史的线性更好:
|
||
|
||
```bash
|
||
git rebase [-i] [upstream]
|
||
```
|
||
|
||
通过增加 -i 参数可进入交互模式。使用 Rebase 还可以将多次提交进行合并,或设置起止点。
|
||
|
||
```bash
|
||
git rebase [-i] <start commit id> <end commit id>
|
||
# 合并最后 n 次提交
|
||
git rebase [-i] HEAD~<n>
|
||
# 合并某个 commit id 以来的提交
|
||
git rebase [-i] <to commit id>
|
||
```
|
||
|
||
使用 -i 参数进入交互模式后,可以:
|
||
|
||
* pick:保留该commit(缩写:p)
|
||
* reword:保留该commit,但我需要修改该commit的注释(缩写:r)
|
||
* edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
|
||
* squash:将该commit和前一个commit合并(缩写:s)
|
||
* fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
|
||
* exec:执行shell命令(缩写:x)
|
||
* drop:我要丢弃该commit(缩写:d)
|
||
|
||
如果发生了冲突,可以在解决冲突并 add 后,通过:
|
||
|
||
```bash
|
||
git rebase --continue
|
||
```
|
||
|
||
也可以使用 rebase 直接从另一分支合并代码,从而避免像 merge 那样增加额外节点(相当于 merge 之后再进行一次 rebase 操作):
|
||
|
||
```bash
|
||
# 从 from branch rebase 合并到当前分支
|
||
git rebase <from branch>
|
||
# 从 from branch rebase 合并到 to branch
|
||
git rebase <from branch> <to branch>
|
||
```
|
||
|
||
命令继续 rebase。
|
||
|
||
## 14. 同步 fork 的仓库
|
||
|
||
基本原理是增加上游仓库,然后进行 fetch 和 merge,最后 push 到当前仓库,如果已经添加了上游仓库,无需再次添加。
|
||
|
||
```bash
|
||
git remote add upstream <upstream repository url>
|
||
git fetch upstream
|
||
git merge upstream/master
|
||
git push <repository>
|
||
```
|
||
|
||
## 15. Patch
|
||
|
||
### 15.1. 生成 Patch
|
||
|
||
```bash
|
||
# 生成最近的 1 次 commit 的 patch
|
||
git format-patch HEAD^
|
||
# 生成最近的 3 次 commit 的 patch
|
||
git format-patch HEAD^^^
|
||
# 生成某 commit 以来的修改 patch(不包含该 commit)
|
||
git format-patch <commit id>
|
||
# 生成两个 commit 间的修改的 patch(包含两个 commit. <commit id 1> 和 <commit id 2> 都是具体的 commit 号)
|
||
git format-patch <commit id 1>..<commit id 2>
|
||
# 生成单个 commit 的 patch
|
||
git format-patch -1 <commit id>
|
||
# 生成从根到 <commit id> 提交的所有 patch
|
||
git format-patch --root <commit id>
|
||
```
|
||
|
||
### 15.2. 应用 Patch
|
||
|
||
将所有 Patch 拷贝到某一文件夹下,然后:
|
||
|
||
```bash
|
||
# 检查 patch 是否能够打上,如果没有任何输出,则说明无冲突,可以打上
|
||
git apply --check <patch dir>/*.patch
|
||
# 将谋文件夹下的全部 patch 都打上
|
||
git am <patch dir>/*.patch
|
||
# 当 git am 失败时,用以将已经在 am 过程中打上的 patch 废弃掉(比如有三个 patch,打到第三个 patch 时有冲突,那么这条命令会把打上的前两个 patch 丢弃掉,返回没有打 patch 的状态)
|
||
git am --abort
|
||
# 当 git am 失败,解决完冲突后,这条命令会接着打 patch
|
||
git am --resolved
|
||
```
|
||
|
||
### 15.3. 合并多个 Patch
|
||
|
||
```bash
|
||
# 先应用 patch
|
||
git am <patch>
|
||
# 然后合并提交
|
||
git rebase -i HEAD~n
|
||
# 生成新 patch
|
||
git format-patch HEAD^
|
||
```
|
||
|
||
## 16. Submodule
|
||
|
||
### 16.1. 添加 Submodule
|
||
|
||
在主仓库中:
|
||
|
||
```bash
|
||
git clone <main-repository url>
|
||
cd <main-repository>
|
||
git submodule add <sub-repository url>
|
||
```
|
||
|
||
这时主仓库的状态会有变化,可通过 commit 和 push 提交上传:
|
||
|
||
```bash
|
||
git commit -sm <message>
|
||
git push
|
||
```
|
||
|
||
### 16.2. 在其他地方使用合并后的版本库
|
||
|
||
```bash
|
||
git clone <main-repository url>
|
||
cd <main-repository>
|
||
git submodule init && git submodule update
|
||
# 或
|
||
git clone --recursive <main-repository url>
|
||
```
|
||
|
||
### 16.3. 更新合并后的版本库
|
||
|
||
```bash
|
||
cd <sub-repository url>
|
||
git commit [...]
|
||
cd ..
|
||
git commit [...]
|
||
```
|
||
|
||
### 16.4. 批量操作
|
||
|
||
```bash
|
||
git submodule foreach <command>
|
||
# 例如
|
||
git submodule foreach git checkout master
|
||
git submodule foreach git submodule update
|
||
```
|
||
|
||
### 16.5. 如何保持 Submodule 的同步
|
||
|
||
如果对第三方 Submodule 进行了定制,但是处于某些原因这些修改并不能提交到远程去。那就要先 fork 第三方仓库,然后在 fork 的基础上添加 Submodule。之后自己的修改或第三方有更新都同步到 fork 的仓库上。
|
||
|
||
### 16.6. 删除 Submodule
|
||
|
||
```bash
|
||
# deinit
|
||
git submodule deinit <submodule-name>
|
||
# remove
|
||
git rm <submodule-name>
|
||
```
|
||
|
||
## 17. 环境变量
|
||
|
||
### 17.1. GIT_TERMINAL_PROMPT
|
||
|
||
该变量设置是否允许 git 在终端中弹出提示,如 https 的用户密码输入提示等。如果 git clone 时出现:“terminal prompts disabled”字样,可在终端中进行如下设置:
|
||
|
||
```bash
|
||
GIT_TERMINAL_PROMPT=1
|
||
```
|
||
|
||
## 18. 清理本地仓库
|
||
|
||
由于编译本地仓库等原因生成了许多临时文件,想要清除这些多余的文件可以使用 git clean 命令:
|
||
|
||
```bash
|
||
# i: 交互模式
|
||
# n: 显示将要被删除的文件
|
||
# d: 删除未被添加到 git 路径中的文件(将 .gitignore 文件标记的文件全部删除)
|
||
# f: 强制运行
|
||
# x: 删除没有被 track 的文件
|
||
git clean -ifdx
|
||
```
|
||
|
||
## 19. 外部参考资料
|
||
|
||
1. [Pro Git](https://git-scm.com/book/zh/v2)
|
||
2. [Git Reference Manual](https://git-scm.com/docs)
|
||
3. [更优雅的 git 合并方式](https://www.yisu.com/zixun/94736.html)
|