首先介绍下使用的工具及插件,Git, TortoiseGit, VSCode插件(Git History,Git Graph)
下载安装Git:Git - Downloads
下载安装TortoiseGit及语言包:Download -- TortoiseGit -- Windows Shell Interface to Git
Think in Git
四个区域
当 `clone` 仓库代码到本地后四个区相同
当编辑代码后,`工作区` 与其余三个区不同
当使用 `add` 将修改的代码暂存后,`索引区`与 `工作区` 相同
当使用 `commit` 将修改的代码提交后,`仓库区` 与 `索引区` 和 `工作区` 相同
当使用 `push` 将修改的代码推送后,四个区的信息又再次相同
工作区 Workspace
从远程区获取代码使用 `pull(fetch + checkout)`
从仓库区获取代码使用 `checkout`
向索引区添加代码使用 `add`
索引区 Index / Stage
向仓库区提交代码使用 `commit`
移除代码到工作区 `reset`
仓库区 Repository
从远程区获取代码使用 `fetch/clone`
向远程区推送代码使用 `push`
从索引区得到代码使用 `commit`
向工作区检出代码使用 `checkout`
远程区 Remote
从仓库区获取代码使用 `push`
特殊文件
FETCH_HEAD
每个分支对应一行,记录最后一次 `fetch/pull` 下来对应分支的最新 `commitID`
HEAD
记录当前分支,`ref: refs/heads/<br>`
ORIG_HEAD
当执行 `reset/merge/rebase` 操作时记录原本 `HEAD` 值
COMMIT_EDITMSG
记录最后一次 `commit` 时填写的日志信息
配置
首要配置
bash
git config --global user.name "YourName"
git config --global user.email "YourEmail"
bash
# 基础命令
git config --system/global/local
--get
--add
--unset
-l, --list
# 配置默认提交信息模板
git config --global commit.template '~/commit-template'
# 配置默认提交信息编辑器
git config --global core.editor "vim"
# 证书校验
git config --global http.sslverify false
# 禁止文件中文名转义
git config --global core.quotepath off
# 在git为2.36.1的版本中, core.quotepath 默认设置为 true,
# 在git输出路径指令时, 控制字符、用反斜杠转译的字符或者字节树大于0x80被认为是"不寻常"的字符
# 如果该变量设置为false, 则这些字符不会被认为是异常字符, 会正确按照UTF-8编码展示
# 代理
git config --local/global/system http.proxy <addr>
git config --local/global/system https.proxy <addr>
秘钥创建
bash
# 使用rsa算法为<邮箱地址>这个内容生成大小在2048B以下的秘钥文件test
# 同时还会有公钥文件test.pub生成
# 若不指定-f参数则会在~/.ssh/下生成秘钥文件id_rsa和公钥文件id_rsa.pub
ssh-keygen -t rsa -C "邮箱地址" -b 2048 -f test
# 将公钥信息添加到github等托管平台
# 测试是否添加成功
ssh -T git@github.com
常见问题
- 使用
ssh -T git@github.com
测试时报错Permission denied
,修改如下文件权限即可:
id_rsa
文件的权限是-rw-------
id_rsa.pub
文件的权限是-rw-rw-r--
多账户
- 使用
-f
参数创建多个秘钥并添加到对应平台 - 修改
~/.ssh/config
,格式如下 - 测试
ssh -T <主机名>
- 新格式仓库地址:
<主机名>:<仓库所有者>/<仓库名>.git
bash
# ~/.ssh/config
# 主机名随意,但须保证文件内唯一
Host <主机名>
# 托管平台,有很多,常用的有github, gitee, gitlab
HostName github.com
# 用户名固定是git
User git
# 对应平台的秘钥文件
IdentityFile <秘钥文件>
# 此时<主机名>等效于git@github.com
# 原本使用的仓库地址git@github.com:<仓库所有者>/<仓库名>.git
# 等效的新格式仓库地址<主机名>:<仓库所有者>/<仓库名>.git
托管平台
gitlab
设置中文显示:Settings -> Preferences -> Localization -> Language
gitee
邮箱管理,禁止命令行推送暴露个人邮箱:开启后账号绑定的邮箱将无法推送
命令别名
bash
# vim ~/.bashrc
# 增加如下内容
alias gr='git remote show origin'
alias gb='git branch'
alias gbv='git branch -vv'
alias gs='git status'
alias ga='git add'
alias gc='git commit'
alias gco='git checkout'
alias gp='git pull'
alias gps='git push'
alias grh='git reset --hard HEAD~1'
alias grs='git reset --soft HEAD~1'
alias grm='git reset --mixed HEAD~1'
alias gd='git diff'
alias gl='git log'
clone
bash
git clone URL -b BRANCH path
--depth 1 # 日志中只有最近1次提交
--bare # 以镜像的形式拉取代码
--mirror # 以镜像的形式拉取代码,与--bare相比,--mirror不仅将源的本地分支映射到目标的本地分支,还映射所有引用
commit
bash
# 将添加到索引区的文件提交到仓库区
git commit
-s, --signoff # 提交日志中自动在最后追加Signed-off-by信息行
--amend # 追加到上一次commit中, --no-edit表示不对提交信息进行修改
-e, --edit # 弹窗编辑框编辑提交说明
-n, --no-verify # 不启用pre-commit和commit-msg
# 允许不提交任何文件,目的是触发CI可能是
git commit --allow-empty -m "chore: re-trigger build"
# 允许不填写提交日志
git commit --allow-empty-message
push
bash
# 推送到远端
git push <alias> <br>:<rbr> # 远端没有rbr分支则创建,但不会自动建立跟踪
git push <alias> :<rbr> # 删除远端分支
fetch
bash
# 拉取所有远端仓库中所有分支
git fetch # FETCH_HEAD 记录所有远端仓库中所有分支最新 commitID
# 拉取某个远端仓库中所有分支
git fetch <alias> # FETCH_HEAD 记录某个远端仓库中所有分支最新 commitID
# 拉取某个远端仓库中某个分支
git fetch <alias> <br> # FETCH_HEAD 记录某个远端仓库中某个分支最新 commitID
pull
bash
# 更新代码到本地分支
git pull
git pull <alias>
git pull <alias> rbr # 导致FETCH_HEAD有只有一条
git pull <alias> rbr:br # 导致FETCH_HEAD有只有一条
git pull --rebase # 使用rebase合并代码
merge
bash
# 整理差异产生新提交
git merge <br> # 将br分支合并到当前分支
git merge --continue # 解决完冲突后继续合并
git merge --abort # 取消本地合并,回到操作前,没有代码残留
git merge --quit # 终止,有提交和代码残留
# 当<br>完全包含当前分支提交时,当前分支直接指向<br>即可,快读合并
# 其他参数
-ff # 默认使能,对于那些不可能执行快速合并的情况下加不加没有分别
--no-ff # 取消,即使完全包括也会产生一次提交留痕
cherry-pick
bash
# 指定某次提交
git cherry-pick <commitID>
# 后面跟两个提交表示范围(], 左开右闭合;若想实现[]则需要使用commitID^
# 分支的最新提交
git cherry-pick <br>
rebase
bash
# 在目标分支上 cherry-pick 本分支提交
# rebase, "移动"目标提交到本分支,遍历本分支提交产生新的提交追加目标提交后
# 目标未修改, 不做处理
# --no-ff # 不难理解,不使用快速合并。由于目标未修改,所以没有"移动"动作,直接遍历本分支提交产生新的提交追加目标提交后
# 本分支未修改, 本分支直接指向目标分支
# --no-ff # 不难理解,不使用快速合并。"移动"目标提交到本分支,由于本分支没有提交,则不会产生新的提交,就像是直接指向目标分支一样
git rebase -i HEAD~2
p, pick <commitID> # 保持不变
r, reword <commitID> # 保持该提交,但会编辑提交信息
e, edit <commitID> # 保持该提交,后续使用git commit --amend修改提交内容及信息,然后使用git rebase --continue继续
s, squash <commitID> # 将本提交合并到上一次提交中,然后编辑提交信息
format-patch和am
bash
git format-patch -n # 当前分支最近n次提交
git am <> # 应用补丁
reset
bash
# 操作HEAD的指向,修改当前分支仓库区提交树
git reset option commitID
--soft # 不碰索引区和工作区,只修改HEAD指向
--mixed # 不碰工作区,重置索引区,修改HEAD指向
--hard # 重置工作区和索引区,修改HEAD指向
--merge
--keep
revert
bash
git revert option commitID
-n, --no-commit # 不直接提交,恢复的文件保存在本地索引区
--no-edit # 不弹出编辑日志界面,直接提交
# 恢复 commitIDA 到 commitIDB, 验证失败
git revert option commitIDA..commitIDB
# 恢复完冲突了
git revert --abort
git revert --quit
clean
bash
# 默认值删除未被版本控制的文件,通过下列选修改删除的范围
git clean -n # 演习,告知哪些文件会被删除
git clean -d # 删除目录,默认情况下不会删除未被版本控制的文件夹及其子文件
git clean -x # 删除忽略文件,默认情况下不会删除忽略的文件
git clean -X # 只删除忽略文件
git clean -f # 强制
remote
git remote, 显示所有远端库别名
origin
git remote -v, 显示所有远端库别名 + url,每个别名都有与之对应的fetch(下载)和push(上传)地址
origin https://gitee.com/zhangguangxuan/Documents.git (fetch)
origin https://gitee.com/zhangguangxuan/Documents.git (push)
git remote show origin
* remote origin
Fetch URL: https://gitee.com/zhangguangxuan/Documents.git
Push URL: https://gitee.com/zhangguangxuan/Documents.git
HEAD branch: master
Remote branch: 远端分支
master tracked(已跟踪)
...
Local branch configured for 'git pull': 本地可直接git pull的分支
master merges with remote master
...
Local ref configured for 'git push': 本地可直接git push的分支
master pushes to master (up to date)
...
git remote add alias url
git remote prune alias, 删除远端库中不存在的分支
git remote rename old_alias new_alias
git remote update
git remote get-url alias
stash
git stash [save]
pop `<ID>` 弹出ID号暂存修改作用于当前分支,默认最新
apply `<ID>` 提取ID号暂存修改作用于当前分支,默认最新
create 创建暂存
store `<ID>` 将暂存存到栈中
branch `<ID>` 弹出ID号暂存创建分支,默认罪行
clear 删除所有暂存
drop `<ID>` 删除ID号暂存
list 显示所有暂存,ID号暂存,在某分支上,路径信息
stash@{0}: On sanjuan/master: systemtest/configs/
show `<ID>` 显示ID号暂存修改,默认最新
diff
git diff 按行显示修改
--word-diff 按单词显示修改
git diff --name-only FETCH_HEAD..FETCH_HEAD^
git show commitId, 查看修改的详情
# 显示大量的文件mode被修改
git config --global core.filemode false
submodule
# 添加子模块
git submodule add git@ssh:xxx.git pod-library
git submodule update --init --recursive
git submodule foreach git pull
branch管理
bash
# 创建本地分支
git branch <br> # 创建后不会切换分支,不会建立跟踪
git checkout -b <br> # 切换分支,若不存在则创建,存在则报错,不会建立跟踪
git checkout -b <br> origin /<rbr> # 切换分支,若不存在则创建,与远端建立跟踪
# 推送本地分支
git push origin <br>[:<rbr>] # 将分支推送到远端,但不会建立跟踪
# 删除本地分支
git branch -d <br> # 有代码未合并会提示错误
git branch -D <br>
# 删除远端分支
git push origin :<br>
git push origin --delete <br>
# 建立分支跟踪
git branch --set-upstream-to=origin/<rbr> [<br>]
# 其他参数
-a # 所有分支
-r # 远端分支
-m # 移动(重命名)分支
-M # 强制移动(重命名)分支
tag管理
bash
# 创建本地标签
git tag <tag> [<commitID>]
# 推送本地标签
git push origin <tag>[:<tag>]
git push origin --tags # 推送所有tag
# 删除本地分支
git tag -d <tag>
git tag -D <tag>
# 删除远端分支
git push origin :regs/tags/<tag>
git push origin --delete <tag>
# 其他参数
-l 所有tag
查看日志
git log
commit <commitID>
Author: <user><<email>>
Date: <time>
<info>
Change-Id: <changeID>
git log -p
# 在 git log 的基础上追加补丁信息
diff --git <file> <file>
index 54f466c..292b0df 100755
--- <file>
+++ <file>
@@ -252,7 +252,7 @@
.............
git log --stat
# 在 git log 的基础上追加各个文件修改行信息
<file> | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
# 不携带具体文件信息
--shortstat
1 file changed, 1 insertion(+), 1 deletion(-)
git log --name-only
# 在 git log 的基础上追加修改的文件
<file>
# 携带文件修改状态
--name-status
M <file>
git log --pretty=<>
oneline == git log --oneline, 只有 commit(短) msg
medium 默认
short 比默认少 Date 和 Change-Id, 即,只有 commit Author msg
full 比默认多 Commit Merge, 少 Date
fuller 比full多 AuthorDate CommitDate
email
From <commitID> <time>
From: <user> <<email>>
Date: <time>
Subject: [PATCH] <info>
Change-Id: <changeID>
raw 比默认多 tree parent committer, 少 Date
format:
%H 显示hash
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 显示父节点hash
%p 父对象的简短哈希字串
%ad 显示作者时间 Mon May 15 09:40:07 2023 +0800
%cd 显示提交时间 Mon May 15 09:40:07 2023 +0800
--date=format:%Y-%m-%d %H:%M:%S 指定时间显示格式
%ae 显示作者邮箱
%ce 显示提交者邮箱
%an 作者(author)的名字
%cn 提交者(committer)的名字
%ar 作者修订日期,按多久以前的方式显示
%cr 提交日期,按多久以前的方式显示
%s 显示主题
%b 显示内容
git log --date=<>
relative == git log --relative-date
local 本地时间
iso ISO 8601 format
rfc RFC 2822 format
short YYYY-MM-DD format
raw %s %z format
format
%a:星期缩写, Tue
%A:星期全称, Tuesday
%b:月份缩写, Jul
%B:月份全称, July
%c:时间全称, Tue 04 Jul 2023 02:24:58 PM GMT
%d:日期 (01 -- 31), 04
%H:小时 (00 -- 23), 14
%I:小时 (01 -- 12), 02
%j:一年中第几天 (001 -- 366), 185
%m:月份 (01 -- 12), 07
%M:分钟 (00 -- 59), 27
%p:上午下午, AM/PM
%S:秒数 (00 -- 59), 58
%U:一年中的第几周,周日为一周的开始 (00 -- 53), 27
%w:星期编号 (0 -- 6; 周日 is 0), 2
%W:一年中的第几周,周以为一周的开始 (00 -- 53), 27
%x:本时区的日期, 07/04/2023
%X:本时区的时间, 02:24:58 PM
%y:2位年份 (00 -- 99), 23
%Y:4位年份, 2023
%z, %Z:时区编号和时区名称缩写, +0000 GMT
%%:Percent sign
其他参数
# 显示7位commit
--abbrev-commit
# 显示提交时间与当前时间差
--relative-date
# 显示 graph 信息
--graph
显示数量
-n 显示前n条
--after 在之后
--until 结束时间
--before 在之前
--since 开始时间
--author 作者
--grep 内容
-- 文件
<br> 分支
--branches 所有分支,只是本地的所有分支
--no-merges 忽略合并的提交,两个分支合并代码时可能出现两个父节点的节点,该节点就是合并的提交,同理还有--merges参数
TortoiseGit
秘钥工具
设置 -> 网络 -> SSH客户端
C:\Program Files\Git\usr\bin\ssh.exe, 使用 ssh-keygen -t rsa -C '邮箱'创建的秘钥, 位置在~/.ssh/id_rsa.pub
C:\Program Files\TortoiseGit\bin\TortoiseGitPlink.exe, 使用PuTTY Key Generator工具创建的秘钥