NotePublic/Software/Applications/Git/Git_使用说明.md

526 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)