Git 常用操作

Git 是一个免费的开源分布式版本控制系统,旨在快速高效地处理从小到大的项目。

安装 Git

在 macOS 上推荐使用 Homebrew 安装 Git。

$ brew install git

设置密钥

权限校验有两种方式:密码和密钥。推荐使用密钥校验。

备注:如果已经有私钥了,可以从私钥生成公钥
ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub

生成秘钥:

$ ssh-keygen -t rsa -b 4096 -C "your.name@gmail.com"

复制生成的公钥,加入到 GitHub 上:Settings > Access > SSH and GPG keys

$ clip < ~/.ssh/id_rsa.pub          # 在 Windows 上复制到剪切板
$ clipcopy ~/.ssh/id_rsa.pub        # zsh

这样,访问 Git 远程仓库时,不需要每次都输入密码了。

设置身份信息

在本地电脑上,设置提交人的身份信息

$ git config --global user.name "Your Name"
$ git config --global user.email "your.name@gmail.com"

协同开发

团队公共仓库需要用到两种分支:

举个例子,假设我们有个项目,团队公共仓库叫 nighon,我的私有仓库叫 john。 首先从公共仓库(nighon)Fork 到自己的仓库(john)下面 nighon/master => john/master

然后拉取仓库到本地电脑

$ git pull git@github.com:john/myapp.git

接着设置远程的 origin 仓库地址

$ git remote set-url origin git@github.com:john/myapp.git

再从公共分支合并到自己的主分支,同样要设置远程的 upstream 仓库地址

$ git remote add upstream git@github.com:nighon/myapp.git

最后,查看一下设置结果是否正确 git remote -v

开发过程中,需要拉取并合并 nighon/master => john/master(本地)

$ git fetch upstream
$ git checkout master
$ git merge upstream/master

每次需要添加功能时,通常会新建一个分支。从 master 新建分支

$ git checkout -b my-awesome-feature master

# 或者是为修复问题而新建分支 (fix issue)
$ git checkout -b fix-something-wrong master

把功能分支合并回主分支

何时使用 merge 和 rebase

什么情况下应该使用 --no-ff(记录一个明确的提交,而不是 Fast Forward)

每次开发完成功能分支后,把功能分支合并到主分支的步骤:

# This moves your feature branch commits on top of the latest commits from main,
# resulting in a linear and clean history.
# 这会将您的功能分支提交移至主分支的最新提交之上,从而产生线性且干净的历史记录。
$ git checkout feature-branch
$ git rebase main

# Using interactive rebase (-i), you can squash commits, edit commit messages,
# and reorder commits to create a more concise and meaningful history.
# 使用交互式变基(-i),您可以压缩提交、编辑提交消息并重新排序提交以创建更简洁、更有意义的历史记录。
# $ git rebase -i main

# 当您在 feature-branch 上时,与 git rebase main 等效的命令是:
# git rebase main feature-branch

# Merge the feature branch into main with --no-ff
# 使用 --no-ff 将 feature 分支合并到 main
$ git checkout main
$ git merge --no-ff feature-branch  # `git config --global merge.ff false` && `git merge feature-branch`

# Delete the feature branch (optional):
# 删除 feature 分支(可选):
$ git branch -d feature-branch
$ git push origin --delete feature-branch
# 推送到 dev1 分支
$ git commit -m 'something'
$ git push origin dev1

# 当前分支是 dev1
# 把 dev1 分支强制推送到 dev2 分支(**注意会覆盖 dev2**$ git push origin +HEAD:dev2

常用配置

$ git config core.ignorecase false                      # 不忽略文件名大小写

常用指令 (Cheat Sheet)

HEAD~ 为示范 commit id
README.md 为示范文件名

$ git checkout HEAD~ -- README.md                       # 恢复文件
$ git clean -fd                                         # 清除未包含的文件
$ git push origin +HEAD~:master                         # 强制推送(覆盖)远程分支
$ git log -p -- README.md                               # 列出单个文件历史改动记录
$ git log --follow -- README.md                         # 列出单个文件历史改动记录
$ git log README.md                                     # 这是查看文件提交历史记录的最基本方法。
$ git blame README.md                                   # 这将列出所有提交已对指定文件进行的操作,以及每次提交的作者以及提交的日期和时间。
$ git diff HEAD~                                        # 列出改动
$ git diff-tree --no-commit-id --name-only -r HEAD~     # 列出改动的文件
$ git branch -d my-awesome-feature                      # 删除本地分支
$ git -C ../nighon.github.io status                     # 切换目录,再进行操作
$ git commit -m "Your commit message" --no-verify       # 跳过语法检查的钩子 Bypass Hooks pre-commit
$ git revert <commit-hash>                              # 撤销特定的 commit
$ git revert <oldest-commit-hash>..<newest-commit-hash> # 撤销一系列的 commit
$ git reflog show <branch-name>                         # 查看某个分支的 reflog
$ git reset --hard <reflog-index>                       # 恢复到某个历史节点
$ git reflog expire --expire=now --all                  # 清理 reflog 记录

branch,tag 操作

$ git tag rc-1                                          # 新建 tag, -a 'create release candidate 1'
$ git push origin --all                                 # 推送所有 branches
$ git push origin --tags                                # 推送所有 tags
$ git remote prune origin                               # error: 一些本地引用不能被更新;尝试运行 'git remote prune origin' 来删除旧的、有冲突的分支

忽略不在 .gitignore 中的文件(这个设置只对本地生效)

$ vim .git/info/exclude
.dockerignore
Dockerfile
docker-compose.yml