「Git」从被动到主动
记录Git的常用命令及使用技巧。
Contents
常用命令
详细教程参考
初始化
1. 用户初始化
# system: `/etc/gitconfig`@linux, `path-to-install-git/gitconfig`@windows
git config --system user.name "yirami"
git config --system user.email "i@yirami.xyz"
# (✓) global: `~/.gitconfig`
git config --global user.name "yirami"
git config --global user.email "i@yirami.xyz"
# project: `path-to-project/.gitconfig`
cd `path-to-project`
git config user.name "yirami"
git config user.email "i@yirami.xyz"
# don't check file mode change
git config --add core.filemode false
2. 密钥初始化
# 针对不同用途创建不同的密钥
ssh-keygen -t rsa -f ~/.ssh/id_rsa -C "i@yirami.xyz"
ssh-keygen -t rsa -f ~/.ssh/id_rsa_yirami -C "i@yirami.xyz"
ssh-keygen -t rsa -f ~/.ssh/id_rsa_singulato -C "tangzhiyong@singulato.com"
# 多密钥管理方式:
# 1) (×)ssh-agent:该方法为一次性的,重启shell需重新添加
# 2) (✓)所有平台使用同一个密钥,哈哈
# 3) 通过配置文件管理:
vim ~/.ssh/config
Host github
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_yirami
Host gitlab
HostName 10.2.2.11
User git
Port 8000
IdentityFile ~/.ssh/id_rsa_singulato
ssh -T git@github.com # testing
ssh -T git@10.2.2.11
3. 仓库初始化
mkdir project_name
cd project_name
git init
git init --bare # 裸仓库,仅存储历史
本地操作
- git stash | 暂存改动到草稿
git stash list # 查看当前的草稿栈
git stash push -m "desc"
git stash pop # 弹出第一个,及stash@{0}
git stash pop stash@{num} # 弹出第num+1个
- git add | 将工作区文件添加到暂存区(stage)
git add . # 添加所有改动到暂存区
git add file_name # 添加某改动文件到暂存区
- git commit | 提交暂存区改动
git commit -m "..."
- git diff | 比较差异
git diff [file] # 比较工作区与暂存区的差异
git diff --staged [file] # 比较暂存区与HEAD的差异
git diff [first-branch]...[second-branch] # 比较两次提交的差异
- git show | 查看提交的改动
git show commit_hash # 查看commit_hash有什么改动
git show file # 查看当前提交中file有什么改动
- git branch | 编辑分支
git branch # 显示仓库本地所有分支
git branch name # 创建name分支
git branch -d name # 删除name分支
git branch -m old new # 重命名分支
- git checkout | 切换或创建分支
git checkout branch_name # 切换到分支branch_name
git checkout -b branch_name # 创建branch_name分支并切换过去
git checkout --orphan branch_name # 创建空分支
git checkout -- file_name # 撤销对file_name的修改(注意`--`与切换分支区分)
- git reset | 版本回退
git reset --hard HEAD # 强行恢复到HEAD提交(所有文件均改动)
git reset --hard HEAD^^ # 强行恢复到HEAD之前2个提交(所有文件均改动)
git reset --hard HEAD~2 # 强行恢复到HEAD之前2个提交(所有文件均改动)
git reset --hard commit_hash # 强行恢复到commit_hash提交(所有文件均改动)
git reset --soft commit_hash # HEAD指向commit_hash提交(但文件不变)
-
git merge | 合并分支
-
git rebase | 变基(避免通过分支合并的方式合并修改)
git rebase other_branch # 将当前分支从other_branch上分叉出的提交节点改变到最新提交,看起来就像把当前分支中新的提交强行挪到了other_branch最新提交之后
git rebase -i # 交互式提交编辑,通过修改为`s`进行提交合并
-
git status | 查看上次提交(commit)后工作区的文件改动
-
git log | 查看仓库提交(commit)历史
git log
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%Cblue%cn%Cgreen, %cr)%Creset' --abbrev-commit --date=relative
-
git reflog | 查看参考历史(常用于恢复)
-
git clean | 删除未跟踪文件
# 删除未跟踪文件
git clean -f
# 删除未跟踪文件(含目录)
git clean -fd
# 删除未跟踪文件(含目录及被ignore排除的部分)
git clean -xfd
# 删除未跟踪文件(预先展示将删除哪些文件)
git clean -nf
与远程端互动
- git clone | 从远程仓库克隆
git clone [-b master] <repo> [dir] # 从仓库克隆master分支到本地dir目录
- git remote | 连接远程仓库
git remote -v # 显示本地仓库连接的所有远程仓库
git remote add repo_name repo_url # 新增远程仓库连接
git remote set-url --add repo_name repo_url # 远程仓库新增多个地址,push时都推送,pull时仅第一个有效
git remote remove repo_name # 删除远程仓库连接
git remote prune repo_name --dry-run # 删除本地失效的远程仓库repo_name的跟踪
- git fetch | 拉取远程分支到本地分支(一般不是当前分支)
git fetch repo_name remote_branch:local_branch # 从repo_name拉取分支remote_branch到local_branch
- git push | 推送本地分支到远程分支
git push repo_name local_branch:remote_branch
git push -f repo_name local_branch:remote_branch # 强制推送(远程仓库需有对应权限)
- git pull | 拉取远程分支到本地分支(一般为当前分支)
git pull repo_name remote_branch:local_branch # 从repo_name拉取分支remote_branch到local_branch
git pull -f repo_name remote_branch:local_branch # 强制拉取
- git tag | 操作标签
git tag --list # 列出标签
git ls-remote --tags repo_name # 列出repo_name的标签
git tag tag_name # 创建标签
git tag -a tag_name -m 'tag_description' # 创建带注释的标签
git show tag_name # 查看标签信息
git tag -d tag_name # 删除标签
git push repo_name tag_name # 推送标签到远程
git push -d repo_name tag_name # 删除(远程)标签
git push repo_name --tags # 推送所有标签到repo_name
git fetch repo_name 'refs/tags/*:refs/tags/*' # 从repo_name拉取所有tag
高级操作
.gitconfig
git submodule
在一个项目中包含另一个项目,可以使用子模块。
# 添加子模块(可指定存放路径)
git submodule add https://github.com/pybind/pybind11 [third_party]
# 检查仓库变化
git status
git diff --cached --submodule
# 克隆包含子模块的项目
git clone xxx
git submodule init
git submodule update
# 克隆包含子模块的项目(简单)
git clone --recurse-submodules xxx
git hook
git hook 类似于回调函数,可以在发生某些事件时触发自定义脚本。自定义脚本需没有扩展名,且具备可执行权限。
脚本存储在
.git/hooks/
(git init
)或hooks
(git init --bare
)下。Hook脚本不会被管理同步
1. 本地端
- pre-commit | 在Git请求你输入提交日志或者生成提交对象前触发
没有参数传递给pre-commit脚本,并且非零状态时候退出会暂停整个提交
- prepare-commit-msg | 在pre-commit后操作输入提交信息的文本编辑器后触发
这是为压缩(squashed)或者合并提交时修改自动生成提交信息的最佳时机
- commit-msg | 在用户输入提交日志时触发
可以提示提交的日志不符合标准
- post-commit | 在commit-msg后触发,不能改变git commit操作的结果
可以用来发送通知
- post-checkout | 切换分支后触发
可以用于清理工作目录生成的文件
-
pre-rebase | 在git rebase调用前触发
-
pre-push | 发起git push前触发
2. 服务端
-
pre-receive | 接受客户端git push前触发
-
update | 在pre-receive后但真正更新之前触发
-
post-update |
-
post-receive | 接受客户端git push成功后触发
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。