Git 操作手册

Huy2023年2月1日大约 17 分钟linuxlinux

记录一些常用的 Git 命令,旨在一文弄懂所有常用的 Git 指令。

新建项目操作

  1. 克隆项目到本地:git clone xxxxx

  2. 设置 Git 用户信息:

  3. 设置 GPG 签名:

    若无 GPG 秘钥,可看 GIthub 添加 GPG 签名 一文。

    • 列出本地公钥:

      $: gpg --list-keys
      
      /xxxx...xxxx/pubring.kbx
      -----------------------------
      pub   edxxx 2023-xx-xx [SC] [expires: 2025-xx-xx]
            C1Fxxxxxxx79D
      uid           [ultimate] yourName <123xxx678+yourEmail@users.noreply.github.com>
      sub   cvxxx 2023-xx-xx [E] [expires: 2025-xx-xx]
      
    • 对提交 commit 进行签名:

      $: git config user.signingkey [PRIMARYKEYID]
      
      • 其中 PRIMARYKEYID 为公钥 C1Fxxxxxxx79D
    • 设置自动对 commit 进行签名:

      $: git config commit.gpgsign true
      

    注:上述的 git config 均可在后面添加 --global 将设置变成全局。

分支管理规范

常用的 GIT 操作指令open in new window

日常指令

1 正常开发流程

后续还会具体介绍,开发流程规范。此处介绍正常开发使用的指令:

// 1 列出分支(无参数时, 会列出本地分支)
$: git branch
// 查看本地及远程分支情况
$: git branch -a
// 查看本地分支的追踪情况
$: git remote show origin

// 2 创建分支指令
$: git branch branchname

// 3 切换分支指令(加指令 -b 为创建新分支,并切换过去)
$: git checkout branchname
$: git checkout -b newBranchname

// 4 删除分支
// 4.1 删除本地分支
$: git branch -d branchname
// 4.1.2 强制删除用大写
$: git branch -D branchname

// 4.2 删除远程分支
$: git push origin -d remoteBranchName
$: git push origin :remoteBranchName
// 4.3 远程已删除分支,本地同步
$: git remote prune origin


// 5 合并分支到【当前主分支中去】, 因此需要先切换到"待合并分支"
$: git checkout master
$: git merge --no-ff newBranch

// 6 个人开发,在个人分支上用分基 rebase 合并 master主分支 到个人分支上
$: git checkout myBranchName
    // 开发 xxxx, 开发完成后。先 rebase master 主分支
$: git rebase master
  // 变基后, 再执行步骤5。将个人分支合并到 master 分支上
$: git checkout master
$: git merge --no-ff myBranchName

// 合并完后, 删除本地及远程分支
$: git branch -d newBranch
$: git push origin -d newBranch

git mergegit merge --no--ff 的区别:

git merge几种模式
git merge几种模式

2. 本地与远程端的交互

正常流程是,查看状态、拉取、修改代码后,推送

// 远端数据库操作
// 0. 查看上次提交后是否有对文件进行再次修改, 若加 -s 则为获取简短输出结果
$: git status

// 1. 拉取 git pull 等于 git fetch + git merge
$: git pull

// 本地开发 xxxx, 开发完成后 推送

// 2. 推送
// 2.1 添加文件到暂存区: 单一文件用 git commit xxx
$: git add .
// 2.2.1 将暂存区内容添加到仓库中去
$: git commit -m [message]
// 2.2.2 或者可以不需要执行 git add 命令直接提交代码。 不推荐
$: git commit -a
// 2.3 正常推送
$: git push
// 2.3.1 推送本地所有的分支到远程
$: git push --all

解决冲突

中途会有问题,如多人协作时,可能在你拉取后,别人已经推送了代码。此时,我们要用到一些高级操作,如 rebase 变基。有几种方案:

假设此时,他人已经 push 相关代码到远程端了。

  1. 【方案 1】正常流程,在 push 时,先用 git pull --rebase 拉取变基代码。而后,再解决冲突,推送。

    $: git add .
    $: git commit -m [message]
    // 变基拉取 git pull --rebase 等于 git fetch + git rebase
    $: git pull --rebase
    // 【有冲突】这时Git会停止rebase并让用户去解决冲突,解决完冲突后,用git add命令去更新这些内容,然后不用执行git-commit,直接执行 git rebase --continue, 这样git会继续apply余下的补丁。
    $: git add .
    $: git rebase --continue
    // 在任何时候,都可以用git rebase --abort参数来终止rebase的行动,并且mywork分支会回到rebase开始前的状态
    $: git rebase --abort
    $: git push
    
  2. 【方案 2】先 git stash 临时贮藏代码,正常拉取。而后 git stash pop 推出,解决冲突,推送。

    $: git stash
    // 不同分支, 则用 git rebase <otherBranch>
    $: git pull
    // 推出贮藏
    $: git stash pop
    // 若有冲突 解决冲突; 注意, 若冲突,并不会将贮藏记录消除,还需使用 git stash drop 删除记录
    $: git stash drop
    // 若冲突过多, 可撤销贮藏改变
    $: git reset --hard
    $: git add .
    $: git commit -m [message]
    $: git push
    

个人使用,已经写完代码了,用方案 1 推送;还未写完,则用方案 2 临时贮藏。

版本回退

版本回退需注意 git revertgit reset 的区别

汇总

# 恢复暂存区的指定文件到工作区
$ git checkout [file]

# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout [commit] [file]

# 恢复暂存区的所有文件到工作区
$ git checkout .

# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset [file]

# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard

# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset [commit]

# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard [commit]

# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]

# 新建一个commit,用来撤销指定commit。
# 实际上是多了一次提交且撤销了这次commit提交的改动
$ git revert [commit]

# 暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop

贮藏与清理

贮藏(stash)会处理工作目录的脏的状态——即跟踪文件的修改与暂存的改动——然后将未完成的修改保存到一个栈上, 而你可以在任何时候重新应用这些改动(甚至在不同的分支上)。

1. 贮藏
$: git stash
或者可以添加备注: 方便查找
$: git stash save "save message"

2. 查看
$: git stash list

3. 显示做了哪些改动, 或者加后缀参数,显示其它贮藏。number 为数值
$: git stash show
$: git stash show stash@{number}

4. 应用贮藏, 默认第一个,加后缀为应用其它贮藏。number 为数值
$: git stash apply
$: git stash apply stash@{number}
 4.1 应用贮藏,同时清除该stash
 $: git stash pop

5. 清理贮藏,默认第一个。加后缀为清理其它贮藏。number 为数值
$: git stash drop
$: git stash drop stash@{number}
 5.1 清理所有贮藏
 $: git stash clear

打标签 Tag

# 列出所有tag
$: git tag

# 新建一个tag在当前commit
$: git tag [tag]

# 新建一个tag在指定commit
$: git tag [tag] [commit]

# 删除本地tag
$: git tag -d [tag]

# 删除远程tag
$: git push origin :refs/tags/[tagName]

# 查看tag信息
$: git show [tag]

# 提交指定tag
$: git push [remote] [tag]
$: git push origin [tagname]
// 推送本地所有分支
$: git push origin --tags

# 提交所有tag
$: git push [remote] --tags

# 新建一个分支,指向某个tag
$: git checkout -b [branch] [tag]

# 检出标签
$: git checkout [tagname]

修改 Commit

// 1. 列出 commit 列表:
$: git rebase -i
 1.1 修改 commit 信息
 1.2 修改完后,重复执行如下命令直到完成
  $: git commit --amend --message="modify message by daodaotest" --author="name <email@gmail.com>"
  $: git rebase --continue
  1.3 中间也可跳过或退出 rebase 模式
  $: git rebase --skip
  $: git rebase --abort
// 列出最近的前两条
$: git rebase -i HEAD~2

2. 修改 commit 信息 具体操作
// 修改显示的内容,将 pick 修改为 reword 或者 简写 r [保留提交的分支记录,但是编辑提交的信息]
// 然后:wq保存退出后,会按顺序自动进入需要编辑的提交信息框

3. 查看分支信息: 最近5条
$: git log --oneline -5

4. 若是修改已经 push 的 commmit message, 则在推送push的时候需要加 --force,强制覆盖远程分支上的提交信息。
$: git push --force

git config 定制

git 也支持自定义指令:

比方说,你想添加一个别名,用于添加一个空的提交。 在这种情况下,你可以在配置文件(在 ~/.gitconfig )中添加以下内容:

[alias]
    empty = "git commit --allow-empty"

或者在终端:

$: git config --global alias.empty "git commit --allow-empty"

使用自定义指令:

$: git empty "Empty commit"

也可以在 Git 之外添加其他 shell 命令作为别名。例如,删除一个已经合并到远程的本地分支的别名:

[alias]
    delete-local-merged = "!git fetch && git branch --merged | egrep -v 'master' | xargs git branch -d"

感叹号 ! 告诉 Git 把它作为一个 shell 命令运行,而不是 git 命令。

对于别名,我们做一个 git fetch。然后我们得到合并后的分支,把它作为 egrep 命令的输入,过滤掉 master 分支,然后删除这些分支。

配置代理

配置 Git 全局代理:

访问 Github 走代理模式

# 全局配置 socket5
$: git config --global http.https://github.com.proxy socks5://127.0.0.1:7890

取消代理:

# 取消全局代理
$: git config --global --unset http.proxy
$: git config --global --unset https.proxy

查看 git 配置:

# 查看全局配置
$: git config --global --list
# 查看本地局部配置
$: git config --local --list

#  打开查看 Mac 中的 git config 文件
$: open ~/.gitconfig

查看 git log 提交信息

利用 git log 统计特定时间内提交的代码信息量。

# 依据用户名 username
$: git log --author="username" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

# 依据时间跨度
$: git log --since=2023-01-01 --until=2023-12-31 --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }'

# 输出结果: added lines: xxx, removed lines: xxx, total lines: xxx

俩者也可以结合。

开发流程

  1. develop 分支检出分支 feat/xxx : git checkout feat/xxx
  2. develop 分支检出预发环境测试分支 release/xxxx : git checkout release/xxxx
  3. 开发完成后将各个开发分支合并至 release 分支: 切换分支 git checkout release/xxx 、 合并分支 git merge feat/xxx
  4. 测试通过后,发起 merge request,待 code review 通过后,负责人 merge 代码,即: git checkout develop 、 合并分支 git merge release/xxx

上线流程

Bugfix 流程

持续集成: GitLab CI/CD

若有代码迭代问题,可以考虑是否 加入 GitLab CI/CD 做持续集成, 本文对此概念做简单介绍。

GitLab CI/CD 是一个内置在 GitLab 中的工具,用于通过持续方法进行软件开发 :

Git 提交规范

参考 angular 团队的 git 提交规范。

Commit message 都包括三个部分:Header (必须),Body 和 Footer。

提交格式type(scope): subject , 例如: fix(Button): 修复按钮问题

- type
  - 用于说明 `commit` 的类别,只允许使用下面10个标识。
    - feat:新功能(feature)【会出现在 CHANGELOG 中】
    - fix:修补bug          【会出现在 CHANGELOG 中】
    - docs:文档修改(documentation)
    - style:代码格式修改,不影响代码含义的更改(空格、格式、缺少分号等)
    - refactor:代码重构(即不是新增功能,也不是修改bug的代码变动)
    - perf:性能优化
    - test:测试用例增加/修改
    - chore:对构建过程或辅助工具和库的更改,例如文档生成
    - revert:回退
- scope(可选)
  - 用于说明 `commit` 影响的范围,比如Button组件、store、首页、路由等等,视项目不同而不同。
- subject(可选))
  - 是 `commit` 目的的简短描述,不超过50个字符。
    - 以动词开头,使用第一人称现在时,比如 change,而不是 changed 或 changes
    - 第一个字母小写
    - 结尾不加句号(.)

Body

Body 为此次提交的详细描述,可多行显示。

Footer 仅在 不兼容变动关闭 issue 时 使用:

特殊情况 Revert

在版本回退中的格式为:

Headerrevert: feat(pencil): add 'graphiteWidth' option

BodyThis reverts commit (SHA 标识符).

利用 git-gzopen in new window 规范代码提交

$: npm install -g commitizen
$: npm install -g cz-git
$: echo '{ "path": "cz-git" }' > ~/.czrc
$: npm install -g conventional-changelog-cli
# 自动生成 CHANGELOG.md 文件
$: conventional-changelog -i CHANGELOG.md -s

# 覆盖重写
$: conventional-changelog -i CHANGELOG.md -s -r 0

# 依据 angular 规范
$: conventional-changelog -p angular -i CHANGELOG.md -s

技巧

由于电脑存在多个开发环境,因此可以对 terminal 进行快捷键配置,使得在切换环境时,git 的用户名和邮箱自动切换。

# 打开编辑配置
$: vim ~/.bash_profile
# set github
function set_git() {
    git config user.name "xxxxxx- Your Name -xxxxxx"
    git config user.email "xxxxxx- Your Email -xxxxxx"
    git config user.signingkey xxxxxx- Your Key -xxxxxx
    git config commit.gpgsign true
    echo -e "~(*≧∀≦)ノ Git account named xxxx set up successfully ♪ "
}

# other setting

# set Proxy
function proxy_on() {
    export http_proxy=http://127.0.0.1:7890
    export https_proxy=$http_proxy
    export all_proxy=socks5://127.0.0.1:7890
    echo -e "~ε=ε=┌( >_<)┘ Terminal proxy is enabled ~"
}

function proxy_off(){
    unset http_proxy https_proxy all_proxy
    echo -e "~ ⊂◉‿◉つ Terminal proxy is turned off ~"
}

# change host
function changehost(){
    echo -e "~ ि०॰०ॢी To start modifying the host file(~/etc/hosts), enter the local password ~"
    sudo vi /etc/hosts
    echo -e "~ ( *・ω・)✄╰ひ╯ Hosts update completed ~"
}

参考文档

Loading...