常用命令/技巧

暂存更改为文件

git diff HEAD > FILE    # 对比工作区和当前节点,可以使用git diff hash1 hash2对比两个节点
git apply FILE          # 应用更改

快速合并其他分支

见下图,当前在develop分支,master分支落后。现在想将master移动到develop上。

init --- master --- 【develop】

用两次checkout加一次merge可以实现:

git checkout master  # 切换到master分支
git merge develop    # 将master分支同步到develop
git checkout develop # 切换回develop分支

但文件较多或工作区有修改时这么做并不太方便,可以使用以下命令一步到位:

git fetch . develop:master
git fetch . HEAD:master     # HEAD代表当前节点

子模块(submodule)

submodule对于本仓库而言,仅是一个指针,并不会将submodule的代码重复上传,这样保证了公共代码在云端仅有一份。

git submodule add http://URL                    # 添加引用
git submodule update --init --recursive         # 更新

不同目录使用不同配置

需要修改gitconfig文件了。

[includeIf "gitdir:/path/to/dir/"]
	path = /path/to/dir/.gitconfig

常见问题

修改本地节点的邮箱

若已在本地使用错误的邮箱提交,可使用以下脚本修改后上传。

#!/bin/sh

git filter-branch --env-filter '

OLD_EMAIL="要修改的旧邮箱"
CORRECT_NAME="正确的用户名"
CORRECT_EMAIL="正确的邮箱@邮箱.com"

if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_COMMITTER_NAME="$CORRECT_NAME"
    export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
    export GIT_AUTHOR_NAME="$CORRECT_NAME"
    export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags

全局设置

使git记住用户名密码

git config --global credential.helper store

设置用户名及邮箱

在使用git之前,最好正确设置邮箱名及用户名。

git config --global user.name "用户名"
git config --global user.email "邮箱名@邮箱.com"

对目录文件名大小写敏感

git config --global core.ignorecase false

统一文件换行符

# 设置默认换行符
git config --global core.eol crlf
# 允许混用 lf 和 crlf 两种换行符
git config --global core.safecrlf false

# 将自动转换关闭,避免git自作主张转换换行符
# 若遇到因为换行符不同diff一大堆的情况,可以设置为true解决
git config --global core.autocrlf false

最好使用.gitattributes文件明确指定换行符,避免悲剧:

* text eol=lf
bin/** binary

修改默认编辑器

git config --global core.editor vim

禁用SSL验证

git config --global http.sslVerify false

同步/清理

清理工作区文件

git clean -dXf # (大写X) 只清理.gitignore提到的文件
git clean -dxf # (小写x) 清理所有文件

同步所有本地分支

将本地所有节点fast-forward到远程最新节点。

curl -o /usr/local/sbin/git-ff-all https://raw.githubusercontent.com/changyuheng/git-fast-forward-all-branches/master/git-fast-forward-all
chmod +x /usr/local/sbin/git-ff-all

免责声明:脚本来自 https://github.com/changyuheng/git-fast-forward-all-branches

或者安装hub并使用hub sync命令。

清理远端已删除的分支/标签

远端删除的引用本地并不会主动删除,可以使用下列命令清理。

# 清理分支
git remote prune origin

# 清理标签
git fetch --prune origin "+refs/tags/*:refs/tags/*"

# 同时清理分支和标签
git fetch origin --prune --prune-tags

其中origin是远端名字

清理未被引用到的分支

即没有被分支和标签引用到的分叉(有时找回代码靠的就是这个),这会造成这些分叉永久消失,请谨慎使用。

# 清理未被引用的分支
git reflog expire --expire-unreachable=now --all

# 清理未被引用的分支并压缩
git gc --prune=now

信息/统计

显示分支拓扑关系

去掉无关节点,只显示branch和tag。快速理清分支关系。

git log --oneline --all --graph --decorate --simplify-by-decoration
gitk --simplify-by-decoration --all             # 仅限Windows

或者使用vscode插件git-graph

市场中的原版插件已停止维护,这是某个fork,其中显示拓扑的功能是我加的 :)

更新:又找到一个工具git-big-picture,可以画出图片来。

获取tag信息

# 获取当前节点的tag,当前节点无tag会报错
git describe --tags --exact-match HEAD

# 获取最近的一个tag
git describe --tags --abbrev=0

# 根据最近的tag自动生成信息,我比较喜欢把这个信息编译到二进制里
# 例如我现在运行结果是 v2-last-23-g97edce9-modified
# 代表距离v2-last这个标签过了23个节点,hash是97edce9,并且工作区有修改
git describe --tags --long --dirty=-modified

获取commit哈希值

git rev-parse --short HEAD  # 短哈希
git rev-parse HEAD          # 完整哈希

获取commit日志

用于获取历史所有提交信息

git log --pretty=format:"%h,%ad,%an(%ae) : %s" --date=format:'%Y-%m-%d %H:%M:%S'

添加--no-pager参数可以输出到屏幕

官方文档:https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History

统计代码行数

bash代码,需要在linux环境执行:

git log --format='%aE' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; diff += $1 + $2; loc += $1 - $2 } END { printf "add: %6s, remove: %6s, diff: %6s, sum: %6s\n", add, subs, diff, loc }' -; done

温馨提示:代码行数无法判定贡献值大小

网上能搜到的代码使用用户名统计,这里改为使用email来统计,并增加了diff一栏。