Git
基础命令
git config --global user.name tianchenghang && \
git config --global user.email '161043261@qq.com' && \
git config --global core.autocrlf false && \
git config --global credential.helper store && \
git config --global init.defaultBranch main && \
git config --global core.filemode false
ssh-keygen -t rsa -C '161043261@qq.com'
ssh-keygen -t rsa -C 'yukino161043261@gmail.com' -f ~/.ssh/id_rsa_github
ssh-keygen -t rsa -C 'yukino161043261@gmail.com' -f ~/.ssh/id_rsa_github-2
# vim ~/.ssh/config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github
IdentitiesOnly yes
Host github.com-2
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github-2
IdentitiesOnly yes工作区 add 暂存区 commit 本地仓库 push 远程仓库
git init # 初始化空 git 仓库
git status # 查看 git 状态
git add <filename> # 将工作区的文件添加到暂存区
git rm -r --cached <filename> # 删除暂存区的文件
git commit -m <message> # 将暂存区的文件提交到本地仓库
git commit --amend # 修改最后一次提交的 message
git log # 查看 git 日志
git diff # 查看工作区与暂存区的差异
git diff --staged # 查看暂存区与最近提交的差异
git restore <file> # 放弃工作区修改
git restore --staged <file> # 取消暂存.gitignore
vim ./.git/info/exclude.gitignore 统一忽略规则, ./.git/info/exclude 仅对本地仓库有效
branch (learnGitBranch)
# 查看本地分支
git branch
# 在 HEAD 指向的 commitHash 处创建本地分支
git branch bugfix
# 在指定的 commitHash 处创建本地分支
git branch bugfix <commitHash>
# 删除本地分支
git branch -d bugfix # -D 强制删除
# 切换到本地分支
git switch bugfix # git checkout bugfix
# 查看远程分支
git branch -r
# 创建并切换到本地分支
git switch -c bugfix
git checkout -b bugfix
# 将本地分支推送到远程仓库, 以创建远程分支
git push origin bugfix
# 删除远程分支
git push origin --delete bugfix
# 查看本地分支和远程分支
git branch -amerge
git merge <mergedBranch>
#! git checkout main && git merge bugfix
# bugfix main*
# | |
# *------ main*
#! git checkout bugfix && git merge main
# bugfix* main
# | |
# bugfix* ---*rebase
git rebase <baseBranch> # 将当前分支的提交 rebase 到 baseBranch 后
git rebase <baseBranch> <curBranch> # 将 curBranch 的提交 rebase 到 baseBranch 后
git rebase -i <baseBranch> # 交互式 rebase
git rebase --continue # 解决冲突后继续
git rebase --abort # 放弃 rebase
#! git checkout bugfix && git rebase main
# bugfix* main
# |
# bugfix*
#! git rebase bugfix main
# bugfix, main*
交互式 rebase
交互式 rebase: --interactive, 简写为 -i
常用指令: pick, reword, edit, squash, fixup, drop
git rebase HEAD~5 --interactive
# 合并前 5 个提交为 1 个提交后, 推送本地 main 分支到远程 main 分支
git push origin main --force-with-lease| 指令 | 含义 |
|---|---|
| pick (p) | 保留该提交, 默认 |
| reword (r) | 保留该提交, 修改提交信息 |
| squash (s) | 与上一个提交合并, 保留两者 message |
| fixup (f) | 与上一个提交合并, 丢弃当前 message |
| drop (d) | 丢弃该提交 |
| exec (x), edit (e), break (b) |
HEAD
- branch: branch 是指向提交 (commitHash) 的引用
- 未 detach 的 HEAD (HEAD 等于某个 branch): HEAD 是指向的 branch 的别名 (指向 commitHash 的二级指针)
- detach 的 HEAD (HEAD 不等于任何一个 branch): HEAD 是指向的 commitHash 的别名 (指向 commitHash 的一级指针)
cat .git/HEAD # ref: refs/heads/main
git symbolic-ref HEAD # refs/heads/main分离 HEAD
git checkout main^ # git checkout main~1
git checkout main^^ # git checkout main~2
git checkout HEAD^ # git checkout HEAD~1
git checkout HEAD^^ # git checkout HEAD~2
# 强制移动 main 分支
git branch -f main [main^ | main~1 | HEAD^ | HEAD~1 | <commitHash>]reset & revert
工作区 add 暂存区 commit 本地仓库 push 远程仓库
git reset --soft <ref> # 撤销旧提交, 保留暂存区和工作区 (保留 diff)
git reset --soft HEAD~2 # 撤销 2 个旧提交, 保留暂存区和工作区 (保留 diff)
git reset --mixed <ref> # 撤销旧提交, 保留工作区
git reset --hard <ref> # 撤销旧提交, 丢弃暂存区和工作区 (不保留 diff)
git reset --hard HEAD~2 # 撤销 2 个旧提交, 丢弃暂存区和工作区 (不保留 diff)
git revert HEAD # 创建 1 个新提交, 以撤销 1 个旧提交
git revert HEAD HEAD~1 # 创建 2 个新提交, 以撤销 2 个旧提交
git revert HEAD~2..HEAD # 创建 多个新提交, 以撤销多个旧提交tag
tag 也是别名
# 创建一个指向 HEAD 的标签, 表示 v1.0.0 版本
git tag v1.0.0
# 创建一个指向 commitHash 的标签, 表示 v1.0.0 版本
git tag v1.0.0 <commitHash>
git describe <ref>
# <ref> 可以是 HEAD, branchName, commitHash, tagName 等
# 输出 <tag>_<numCommits>_g<hash>
# tag: 距离 ref 最近的标签名
# numCommits: ref 比 tag 多 numCommits 个提交
# hash: ref 所在的 commitHash 的前缀fetch
- 从远程仓库中下载本地仓库中缺少的提交
- 更新远程分支 origin/main
- 不会更新本地 main 分支, 即不会修改本地文件
当前分支 track origin/main 时, git fetch && git merge origin/main 等价于 git pull
push
fetch + rebase + push
git fetch && git rebase origin/main && git push 等价于 git pull --rebase && git push
fetch + merge + push
git fetch && git merge origin/main && git push 等价于 git pull && git push
本地分支跟踪 (track) 远程分支
默认本地 main 分支跟踪远程 main 分支
# 创建并切换到跟踪远程 main 分支的新分支 anotherMain
git checkout -b anotherMain origin/main
# branch 'anotherMain' set up to track 'origin/main'
#! 等价于
# 创建新分支 anotherMain
git branch anotherMain
# 切换到新分支 anotherMain
git switch anotherMain
# 新分支 anotherMain 跟踪远程 main 分支
git branch -u origin/main
# branch 'anotherMain' set up to track 'origin/main'
#! 等价于
# 创建新分支 anotherMain
git branch anotherMain
# 新分支 anotherMain 跟踪远程 main 分支
git branch -u origin/main anotherMain
# branch 'anotherMain' set up to track 'origin/main'push 参数
git push <remote> <branchName>, 例如 git push origin main
git push -u <remote> <branchName> 设置上游分支
git push --force-with-lease 仅在远程分支没有被其他人更新时, 强制推送
推送本地 main 分支到远程 main 分支 (默认是 HEAD 指向的分支)
git push <remote> <localRef>:<remoteBranchName>
localRef 可以是 HEAD, branchName, commitHash, tagName 等, 例如 git push origin foo^:main
fetch 参数
git fetch <remote> <branchName>, 例如 git fetch origin main
从远程仓库中下载本地仓库中缺少的提交, 并更新远程分支 origin/main
git fetch <remote> <remoteRef>:<localBranchName>
remoteRef 可以是 HEAD, branchName, commitHash, tagName 等, 例如 git fetch origin HEAD^:main
如果只是 git fetch, 则更新该远程的所有远程分支与标签
pull 的参数
git pull <remote> <remoteRef>:<localBranchName>
等价于 git fetch <remote> <remoteRef>:<localBranchName> && git merge <localBranchName>
submodule
git clone <url> --recurse-submodules # 克隆仓库, 初始化/更新子模块
git submodule add <submodule_url> path/to/submodule # 添加子模块, 写入 .gitmodules
git submodule update --init --recursive # 初始化/更新子模块
git submodule update --remote # 更新子模块stash
stash 用于缓存工作区 + 暂存区修改
git stash push -m "wip" # 缓存工作区 + 暂存区修改, 默认不包含未跟踪文件 (untracked)
git stash push -u -m "wip" # 包含未跟踪文件 (untracked)
git stash list # 查看 stash 列表
git stash pop # 应用最新 stash 并出栈
git stash apply stash@{1} # 应用指定 stash, 不出栈
git stash drop stash@{0} # 删除指定 stash
git stash branch fix stash@{0} # 基于 stash 创建分支cherry-pick
将一些提交复制到当前分支
git cherry-pick <commitHash> # pick 单个提交
git cherry-pick <commitHashA> <commitHashB> <commitHashC> # 按顺序 pick 多个提交
git cherry-pick -x <commitHash> # 在 message 中追加 commit 信息
git cherry-pick --continue # 解决冲突后继续
git cherry-pick --abort # 放弃 cherry-pickgit tag
# 删除本地分支
git branch --delete gh-pages
# 删除远程分支
git push origin --delete gh-pages
# 创建 tag
git tag v0.0.1
# 推送 tag
git push origin v0.0.1
# 删除本地 tag
git tag --delete v0.0.1
# 删除远程 tag
git push origin :refs/tags/v0.0.1