Git
安装
核心概念
author vs committer: author 代码是谁编写, committer 是谁合并/提交代码到仓库
head: TBD.
origin: TBD.
upstream: TBD.
stash: TBD.
常用配置
如无特别说明,以下以使用 Github 托管代码为例。
全局配置文件路径
macOS 和 Linux $HOME/.gitconfig Windows %USERPROFILE%\.gitconfig
直接添加或修改文件 .gitconfig 修改全局通用配置
# 设置 author 用户名和邮件地址
[user]
name = Zhang San
email = 12345678+san123456@users.noreply.github.com
[init]
# 默认分支名为 master,不用 main
defaultBranch = master
[core]
# 禁止自动转换文件换行符(CRLF/LF),编辑器保存文件是什么就是什么,要修改用户自己手动修改
autocrlf = false
# 忽略文件权限变更
fileMode = false
# 通过代理访问 Github
[https "https://github.com"]
proxy = socks5h://192.168.1.100:7890注意:Github 上可在 profile 设置 Name ,这个值如果和 gitconfig user.name 不一致,那么通过 Github 网页操作 pr / commit 时会替代 author 值。
在仓库执行 git shortlog -nse 统计时,可能会出现相同邮件地址的 committer 显示为不同的两个 committer(因为 user name 不一样)
266 Zhang San <12345678+san123456@users.noreply.github.com>
4 San <12345678+san123456@users.noreply.github.com>修改 Name 和 gitconfig 一致可以避免这个问题。如果想篡改历史中记录修复,见后面「常见用法」中「篡改历史」说明。
通过命令行设置或修改用户名和邮件地址
git config --global user.name "Zhang San"
git config --global user.email 12345678+san123456@users.noreply.github.comGithub 认证方式 SSH vs HTTPS
优势 劣势
SSH 配置公私钥后,提交或拉取代码时不需要手动输入密码 无法使用 HTTPS 代理
HTTPS 可使用 HTTPS 代理提交或拉取代码 需提前预先配置 HTTP 认证信息配置 Github HTTPS 认证信息步骤
在 Github settings 生成 token
修改全局配置文件 .gitconfig,补充以下
[url "https://<github用户名>:<github token值>@github.com"]
insteadOf = https://github.com.gitattributes
放在仓库根目录(也可放在子目录,只对该目录及其子目录生效),按路径给文件指定属性,作用于换行符、diff、合并、打包、LFS 等。语法为 <pattern> <attr1> <attr2> ...,pattern 规则同 .gitignore。
属性有四种取值形式:attr(设为 true)、-attr(设为 false)、!attr(取消设置)、attr=value(赋值)。
注:.gitattributes 需提交到仓库,对所有 clone 生效,优先级高于 .gitconfig 中 core.autocrlf 等个人配置。
换行符规范化
# 默认由 Git 自动判断是否为文本文件,入库统一存为 LF
* text=auto
# 显式声明文本文件,检出时按平台转换
*.go text
*.md text
# 强制检出为 LF(shell 脚本、Dockerfile 等在 Windows 上也不能是 CRLF)
*.sh text eol=lf
Dockerfile text eol=lf
# 强制检出为 CRLF
*.bat text eol=crlf
*.ps1 text eol=crlf
# 声明为二进制,等价于 -text -diff
*.png binary
*.pdf binary注:* text=auto 只影响新增或再次入库的文件,已在历史中以 CRLF 存储的文件不会自动改写。要一次性规范化整个仓库:
git add --renormalize .
git commit -m "chore: normalize line endings"diff 与 merge 行为
# 指定语言的 hunk header,diff 时显示所在函数名
*.go diff=golang
*.ts diff=typescript
*.css diff=css
# 合并冲突时直接取本地版本,不做逐行合并(适合锁文件、生成产物)
package-lock.json merge=ours
*.pbf -merge
# 生成的文件不参与合并,冲突时保留本地再重新生成
dist/** -diff -mergemerge=ours 需先在 .gitconfig 中注册驱动:
[merge "ours"]
name = keep local version
driver = true从归档中排除文件
git archive 打包(GitHub 的 source tarball 同理)时排除开发用文件:
/.github export-ignore
/.issues export-ignore
/docs export-ignore
.gitattributes export-ignore
.gitignore export-ignore
*_test.go export-ignore关键字展开
# 检出时把 $Id$ 展开为 blob 的 SHA-1
*.txt ident注:Git 不支持 SVN 那样的 $Revision$、$Date$ 展开,只有 ident 一种,一般用 build 时注入版本号代替。
Git LFS
git lfs track "*.psd" 实际就是往 .gitattributes 写一行:
*.psd filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -textGitHub linguist
影响仓库语言统计和 diff 折叠:
# 不计入语言统计,并在 PR diff 中默认折叠
pkg/api/*.pb.go linguist-generated=true
vendor/** linguist-vendored=true
docs/** linguist-documentation=true
# 纠正语言识别
*.h linguist-language=C查看某个文件实际生效的属性
git check-attr -a path/to/file
git check-attr text eol -- path/to/file参考
常见用法
克隆仓库指定版本快照 git clone --depth 1 --branch v1.2.3 https://github.com/foo/bar.git $GOPATH/src/github.com/foo/bar
统计提交者信息 git shortlog -nse
push 到 fork 的 pr git push git@github.com:user/repo local_branch_name:remote_branch_name
从所有历史中删除指定敏感数据
brew install git-filter-repo
git clone https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
cd YOUR-REPOSITORY
git filter-repo --invert-paths --path PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
echo "YOUR-FILE-WITH-SENSITIVE-DATA" >> .gitignore
git add .gitignore
git commit -m "Add YOUR-FILE-WITH-SENSITIVE-DATA to .gitignore"
git remote add origin https://github.com/YOUR-USERNAME/YOUR-REPOSITORY
git push origin --force --all
git push origin --force --tags参考
合并两个仓库
合并 project-a 入 project-b
cd path/to/project-b
git remote add project-a /path/to/project-a
git fetch project-a --tags
git merge --allow-unrelated-histories project-a/master # or whichever branch you want to merge
git remote remove project-a注:可能会触发大量冲突需要手动合并。
发布版本和打标签
列出标签 git tag -l
看标签详情 git show v0.0.1
打标签 git tag -a <tag name, such as v0.0.1> -m "description ..."
删除标签 git tag -d <tag name>
推送标签到上游 git push --tags
修改已有标签 git tag v0.0.35 -f -a
修改已有标签后推送到上游覆盖已有的 git push --tags -f
Push code to gitlab with access token
- Create a Project Access Tokens, http://10.0.0.1:8080/foo/bar/-/settings/access_tokens
- Add remote
git remote add xxx http://<TokenName>:<TokenValue>@10.0.0.1:8080/foo/bar.git - Push code
git push xxx master
https://stackoverflow.com/questions/42074414/gitlab-push-to-a-repository-using-access-token
篡改历史
TBD.
fatal: refusing to merge unrelated histories
解决 git pull origin master --allow-unrelated-histories
注:会覆盖本地未同步到远程仓库的变更。
Git Bash symbolic link
Git 2.46.2 Setup
- Configuring extra options
- Enable symbolic links
gpedit.msc 本地组策略编辑器
- Computer Configuration / 计算机设置
- Windows Settings / Windows 设置
- Security Settings / 安全设置
- Local Policies / 本地策略
- User Rights Assignment / 用户权限分配
- Create symbolic links / 创建符号链接
- 添加用户或组
- Security Settings / 安全设置
- Windows Settings / Windows 设置
此法在 Windows 7 不生效。
Change default branch name to master
git branch -m main master
git config --global init.defaultBranch masterChange last commit message and committer
git commit --amend --author="some-one <123456+some-one@users.noreply.github.com>"
