主页
文章
分类
系列
标签
Git
发布于: 2016-5-27   更新于: 2016-5-27   收录于: Tool , Cheat sheet
文章字数: 5353   阅读时间: 11 分钟  

配置

1
2
3
git config --global "Your Name"
git config --global "Email Address"
git config --global credential.helper store      #保存密码(每次要输密码/重复输密码)

初始化

1
git init

提交修改

1
2
3
4
5
git add <file>
git add -u                                #提交 work directory 中所有已 track 的文件至 staging area
git commit -m "descriptions"
git commit --amend                        #对最近一次的提交做内容修改
git commit --amend --author "user_name <user_email>"    #修改最近提交用户名和邮箱

查看状态、比对

1
2
3
4
5
6
7
8
git status
git status -s                             #文件状态缩略信息, 常见 A:新增; M:文件变更; ?:未track; D:删除
git diff <file>
git diff HEAD -- <file>                   #查看工作区和版本库里面最新版本的区别
git diff --check <file>                   #检查是否有空白错误(regex:' \{1,\}$')
git diff --cached <file>                  #查看已add的内容(绿M)
git diff branch1 branch2 --stat           #查看两个分支差异
git diff branch1 branch2 <file...>        #查看分支文件具体差异

查看历史版本、历史操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
git log
git reflog
git log -n                                #最近n条的提交历史
git log <branch_name> -n                  #分支branch_name最近n条的提交历史
git log --stat                            #历次commit的文件变化
git log --shortstat                       #对比 --stat 只显示最后的总文件和行数变化统计(n file changed, n insertions(+), n deletion(-))
git log --name-status                     #显示新增、修改、删除的文件清单
git log lhs_hash..rhs_hash                #对比两次 commit 的变化(增删的主语为 lhs, 如 git log HEAD~2..HEAD == git log HEAD -3)
git log -p                                #历次 commit 的内容增删
git log -p -W                             #历次 commit 的内容增删, 同时显示变更内容的上下文
git log origin/EI-1024 -1 --stat -p -W    #查看远端分支 EI-1024 前一次修改的详细内容
git log origin/master..dev --stat -p -W   #查看本地 dev 分支比远端 master 分支变化(修改)的详细内容

git log <branch_name> --oneline           #对提交历史单行排列
git log <branch_name> --graph             #对提交历史图形化排列
git log <branch_name> --decorate          #对提交历史关联相关引用, 如 tag, 本地远程分支等
git log <branch_name> --oneline --graph --decorate      #拼接一下, 树形化显示历史
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%ai(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit   #同上, 建议 alais 保存

git log --since --after                   #显示时间之后的提交
git log --until --before                  #显示时间之前的提交
git --author                              #显示指定作者的提交
git --committer                           #显示指定 committer 的提交(注:committer 不一定是 author)
git log -S [keyword]                      #仅显示添加或移除了某个关键字的提交(某些场景比单独git log -p | grep [keyword] 好用很多)
git log origin/b3.3/master --author=yx-ren --since="2019-10-01" --before="2019-11-01"
#查看某作者在某发布版本最近一个月的提交, 常见于线上背锅
git log origin/b3.0/master --author=some_leave --since="1 month ago"
#查看某刚离职同事过去一个月的提交, 常见于背锅
git log --since=1.weeks                   #过去一周的提交(写周报的时候可以看看我这一周干了啥)
git log --since=1.days                    #过去一天的提交(下班的时候可以看看我这一天干了啥)
git log --since="1 weeks 2 days 3 hours 40 minutes 50 seconds ago"
#过去1周2天3小时40分50秒之内的提交

git log –pretty=format 参数

  • %H - 提交对象(commit)的完整哈希字串
  • %h - 提交对象的简短哈希字串
  • %T - 树对象(tree)的完整哈希字串
  • %t - 树对象的简短哈希字串
  • %P - 父对象(parent)的完整哈希字串
  • %p - 父对象的简短哈希字串
  • %an - 作者(author)的名字
  • %ae - 作者的电子邮件地址
  • %ad - 作者修订日期(可以用 –date= 选项定制格式)
  • %ar - 作者修订日期,按多久以前的方式显示
  • %cn - 提交者(committer)的名字
  • %ce - 提交者的电子邮件地址
  • %cd - 提交日期
  • %cr - 提交日期,按多久以前的方式显示
  • %s - 提交说明

版本回退、前进

1
2
3
git reset --hard HEAD^                    #回退到上 1 版本
git reset --hard HEAD~5                   #回退到上 5 个版本
git reset --hard id                       #回退到指定版本

撤销修改

1
2
3
4
git checkout -- <file>                    #撤销修改:误修改工作区文件,未 git add/commit
git restore <file>                        #撤销修改:误修改工作区文件,未 git add/commit
git reset HEAD <file>                     #撤销 git add:误将文件加入暂存区(git add),未 git commit
git reset --hard HEAD^                    #撤销 git commit:误将文件提交(一旦提交,只能通过版本回退进行撤销)

删除与恢复

git rm/add <file>

1
2
3
git commit -m "remove <file>"             #删除版本库中的<file>:删除工作区文件后,继续删除版本库中相应的文件
git checkout -- <file>                    #根据版本库中的<file>恢复工作区<file>
git restore <file>                        #对于 checkout -- <file> 的新写法 (2.23 引入)

清理工作区

未 track 也未 ignore 的文件或文件夹(如各种临时 .swp, .patch 文件等)

1
2
3
4
5
6
git clean -i                              #交互式清理, 不常用
git clean -n                              #查看清理文件列表(不包括文件夹), 不执行实际清理动作
git clean -n -d                           #查看清理文件列表(包括文件夹), 不执行实际清理动作
git clean -f                              #清理所有未track文件
git clean -df
#清理所有未 track 文件和文件夹, 常用, 但使用前确保新增加的文件或文件夹已 add, 否则新创建的文件或者文件夹也会被强制删除

关联远程仓库

本地到远程

1
2
3
4
5
6
7
git remote add origin <remote address>    #在本地工作区目录下按照 GitHub 提示进行关联
git remote rm origin                      #解除错误关联
git push -u origin master                 #第一次将本地仓库推送至远程仓库(每次在本地提交后进行操作)
git push origin master                    #以后每次将本地仓库推送至远程仓库(每次在本地提交后进行操作)
<remote address>:
    git@github.com:<username>/<repository>.git
    https://github.com/<username>/<repository>.git

远程到本地

1
git clone <remote address>                #git 协议速度更快但通常公司内网不允许,https 协议速度慢

分支管理

创建、切换、查看、合并、删除

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
git branch <branch name>                  #创建<branch name>分支
git checkout <branch name>                #切换至<branch name>分支
git switch <branch name>                  #切换至<branch name>分支 (2.23 引入)
git checkout -b <branch name>             #创建并切换至<branch name>分支
git switch -c <branch name>               #创建并切换至<branch name>分支
git branch                                #查看已有分支(* 表示当前分支)
git merge <branch name>                   #合并<branch name>到当前分支(通常在 master 分支下操作)
git merge --no-commit <branch name>       #合并<branch name>到当前分支,但不提交
git branch -d <branch name>               #删除分支
git branch -m oldbranchname newname       #重命名分支

解决合并冲突

合并时报错“分支发生冲突”,首先 vim 相应文件,修改冲突位置,然后按照 git add/commit 重新提交,最后删除多余分支即可。

1
2
git log --graph --pretty=oneline --abbrev-commit
git log --graph

开发流程

  • master 分支 - 发布稳定版本
  • dev 分支 - 发布开发版本
  • <developer name>分支 - 个人开发分支(个人开发完成将该分支并入 dev,同时保留该分支,继续开发)

分支管理

合并后删除分支也在 log 中保留分支记录

1
git merge --no-ff -m "descriptions" <branch name>

Bug 分支管理

软件开发中,bug 就像家常便饭一样。有了 bug 就需要修复,在 Git 中,由于分支是如此的强大,所以每个 bug 都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

1
2
3
4
5
6
git stash                                 #保存当前工作现场(在 dev 未完成开发,但 master 有 bug 需要修复)
git stash pop                             #回到 dev 分支后恢复工作现场(list 中的现场会同时被删除)
git stash list                            #查看当前存储的工作现场
git stash apply stash@{#}                 #回到指定工作现场(list 中的现场不会被删除,需要用 git stash drop)
git stash drop stash@{#}                  #删除指定工作现场
git cherry-pick <id>                      #在 master 修复好 bug 后,在 dev 复制一遍 bug 修复流程

Feature 分支管理

软件开发中,总有无穷无尽的新的功能要不断添加进来。添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个 feature 分支,在上面开发,完成后,合并,最后,删除该 feature 分支。

1
git branch -D <branch name>               #强制删除分支(丢弃未合并分支)

协作与分支推送

  • User 1
1
2
3
4
git remote [-v]                           #查看远程库信息(-v 查看详细信息)
git remote update origin --prune          #更新分支列表(更新远程分支列表)
git remote update origin -p               #更新分支列表(更新远程分支列表)
git push origin [master/dev/...]          #推送指定分支到远程
  • User 2
1
2
3
git clone <remote address>                #克隆到本地(只能克隆 master)
git checkout -b dev origin/dev            #本地新建分支并关联远程
git add/commit/push                       #添加、提交、推送更新
  • User 1
1
2
3
4
5
git add/commit/push                       #推送时报错(与 user 2 推送的更新冲突)
git pull <remote> <branch>
git branch --set-upstream-to=origin/<branch> <branch>          #本地与远程关联
git pull                                  #拉取远程文件(并解决冲突)
git commit/push                           #重新提交并推送

标签管理

常用于版本管理 - 查看、创建、操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
git tag                                                   #查看标签
git show <tag name>                                       #查看指定标签
git log --pretty=oneline --abbrev-commit --decorate=full  #在 log 中显示标签
git tag <tag name>                                        #为上次 commit 位置打标签
git tag <tag name> <commit id>                            #为指定 commit 位置打标签
git tag -a <tag name> -m "descriptions" <commit id>       #为指定 commit 打标并添加描述
git tag -d <tag name>                                     #删除本地标签
git push origin <tag name>                                #推送指定标签到远程
git push origin --tags                                    #推送所有本地标签到远程
git push origin :refs/tags/<tag name>                     #删除远程标签(先删除本地标签)

rebase

rebase 在日常中常用功能主要是两个,多人协同开发定期 rebase master 以及压缩某分支多个 commit
git rebase master 常见于多人开发,每个开发人员从 master checkout 出自己的分支,开发一段时间后提交至 master 之前最好 rebase 一下防止冲突,就算真有冲突在本地解决好过强制提交,开发流程中尽量保证 master 的干净整洁

举个例子:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
master 分支上有三个提交 C1, C2, C3
某一时刻 usr1 在 C3 的 master 分支上 checkout 出新的分支, 用于开发服务端支持 ipv6 新特性, 并提交了 C4, C5
git checkout -b ipv6_support
......
git commit -m C4
......
git commit -m C5
此时提交状态如下所示
      (origin/master branch)
             |
C1 <- C2 <- C3
             \
              \
               \
                C4 <- C5
                       |
                (ipv6_support branch)

某同事 usr2 修改了 master 上的内存泄漏错误, 并提交了 C6, C7, C8 三个 commit, 然后直接推送 origin/master(假设这个期间无其他人推新内容到 master)
此时提交状态如下所示
                    (origin/usr2/fix_mem_leak branch)
                               |
C1 <- C2 <- C3 <- C6 <- C7 <- C8
             \                 |
              \         (origin/master branch)
               \
                C4 <- C5
                       |
                (ipv6_support branch)

如果此时 usr1 希望将 ipv6 的新特性提交至 master, 那么在其直接 push origin master 时会提示 master 需要合并分支 ipv6_support
虽然 C4, C5 的改动内容完全独立于 C6, C7, C8 的改动
但 git 仍会抓取 C5 和 C8 的提交并产生一个新的 C9 commit(因两者分支的 base 不同), 如下图所示
C1 <- C2 <- C3 <- C6 <- C7 <- C8
             \                 \
              \                 \
               \                 \
                C4 <- C5 <------ C9

如果是为了保证 master 提交记录的"干净完整"
或者是某分支不着急提交, 仍需要更多的测试与开发, 但又不想分支开发周期结束后"偏离"当初 checkout 的 master 分支太久远(容易造成更多的冲突)
可以考虑(定期)利用 rebase 来进行变基
即上面提到过的多人协同开发, 定期 rebase master 是个好习惯

git checkout ipv6_support
git rebase master
结果提交状态如下所示
            (origin/master origin/usr2/fix_mem_leak branch)
                               |
C1 <- C2 <- C3 <- C6 <- C7 <- C8
                                \
                                 \
                                  \
                                   C4' <- C5'
                                           |
                                    (ipv6_support branch)
这种 rebase 在功能上类似将某分支所有的改动做成多个 patch 并依次打在指定的新 base 上
此时再提交 master 就不会产生抓取效果, 会将 C4' 和 C5' 直接提交至 master, 即 can be fast-forwarded
同时也保证了 master 提交记录的整洁性
(注: 虽然 C4' 和 C5' 的内容和 C4, C5 完全一致, 但两者 base 不同, commit hash code 也完全不同)

git rebase --noto <branch_lhs> <branch_rhs>
#重放, 用于变基在分支 branch_lhs 中而不在 branch_rhs 中的 commit

#某项目状态分支如下所示, 其中 Cn 的数字代表提交时间顺
# T1 某员工 urs1 从 C2(master 分支)checkout 出一个新的分支用于开发某基础公共组件功能
# T2 员工 usr1 开发完毕提交 C3, 然后继续在该分支上(或 checkout -b server)开发服务端相关功能, 并提交 C4
# T3 master 分支有更新, 其他同事 usr2 提交了 C5, C6 并推送到了 origin master
# T4 员工 usr1 从 server 分支切回到 C3 公共基础的提交, 并创建新分支 client, 用于开发客户端功能, 并提交 C8, C9
# T5 员工 usr1 从 client 分支切回到 server 分支继续开发服务端功能, 并提交 C10
            (master branch)
                   |
C1 <- C2 <- C5 <- C6
         \
          \
           \
            C3 <- C4 <- C10
               \         |
                \ (server branch)
                 \
                  C8 <- C9
                         |
                  (client branch)

# 此时该员工希望将客户端相关的功能合并到主分支并发布,但暂时并不想合并 server 中的修改,因为它们还需要经
# 过更全面的测试。 这时可以使用 git rebase 命令的 --onto 选项,选中在 client 分支里但不在
# server 分支里的修改(即 C8 和 C9),将它们在 master 分支上重放:

git rebase --noto client server
# 得到如下图所示的提交状态
# 注:其中 C3', C8', C9' 与 C3, C8, C9 的提交内容完全一样, 但是 hash id 是完全不同的
            (master branch)(client branch)
                   |            |
C1 <- C2 <- C5 <- C6 <- C8' <- C9'
         \
          \
           \
            C3 <- C4 <- C10
               \         |
                \ (server branch)
                 \
               [#####disable######]
               [  C8 <- C9        ]
               [         |        ]
               [  (client branch) ]

#can be fast-forwarded
git checkout master
git merge client
# 提交后分支状态如下
                                (client branch)
                                       |
C1 <- C2 <- C5 <- C6 <- C3' <- C8' <- C9'
         \                             |
          \                     (master branch)
           \
            C3 <- C4 <- C10
                         |
                  (server branch)

git rebase -i HEAD~n        #压缩当前分支的 n 个 commit 并合并为 1 个 commit, 常见第一行为 pick, 剩下的 n-1 行为 squash
git rebase --abort          # rebase 过程中发生错误, 可以利用该命令终止整个 rebase 过程
git rebase --continue       # rebase 过程中发生冲突, 在解决冲突后可以利用该命令进行后续过程

打 patch(补丁)

生成 diff patch 文件

git 可以识别 diff 文件

1
2
git <branch> log -n -p > diff.patch       #生成某分支过去 n 个 commit 的文件 diff 信息至单个 diff 文件
git diff <--cached> diff.patch            #针对当前缓存区的内容生成 diff 文件

利用 apply 打 patch

1
2
3
git apply --check diff.patch              #检查是否可以正常应用, 无回显证明无冲突
git apply --stat diff.patch               #查看应用 diff 文件后的文件变化
git apply diff.patch                      #打 patch, 仅仅改变文件信息, 无 commit 信息, 仍然需要 add, commit

利用 –format-patch 生成 patch

带 commit 信息

1
2
3
4
5
git format-patch <branch> -n              #生成分支<branch>最近的 n 次 commit 的 patch
git format-patch <r1>..<r2>               #生成两个 commit 间的修改的 patch(包含两个 commit. <r1>和<r2>都是具体的 commit 号)
git format-patch -1 <r1>                  #生成单个 commit 的 patch
git format-patch <r1>                     #生成某 commit 以来的修改 patch(不包含该 commit)
git format-patch --root <r1>              #生成从根到 r1 提交的所有 patch

利用 am 打 patch

1
2
3
4
5
6
git apply --check 0001-update-bash.sh.patch #检查 patch 是否冲突可用
git apply --stat 0001-update-bash.sh.patch  #检查 patch 文件变更情况, 无回显证明无冲突
git am 0001-update-bash.sh.patch            #将该 patch 打上到当前分支, 带 commit 信息
git am ./*.patch                            #将当前路径下的所有 patch 按照先后顺序打上
git am --abort                              #终止整个打 patch 的过程, 类似 rebase --abort
git am --resolved                           #解决冲突后, 可以执行该命令进行后续的 patch, 类似 rebase --continue

bundle(打包)

  • 该命令会将 git 工程打包, 默认情况下会打包所有 commit 记录和 track 的文件
  • 不同于简单粗暴 tar.gz 打包整个文件夹, bundle 只打包那些 push 过的记录
  • 如某 git 工程下存在 .build 构建后的目录, 而 .gitignore 又忽略了该文件夹
  • 如果利用 tar.gz 打包则会将那些忽略的文件文件夹一并打包, 可能会造成压缩包极大的臃肿
  • 而又不想仅仅为了打个包就删除整个 build 目录(如重新 build 时间成本太大)
  • 那么就可以使用 bundle 进行打包, 该命令只打包 track 过的文件
  • 并且像 url 那样直接调用 git clone 来重建
1
2
git bundle create awesome-cheatsheets.bundle HEAD master       #打包重建 master 分支的所有数据
git clone awesome-cheatsheets.bundle                           #重建工程

bundle 也可以打包指定的区间, 至于提交区间有多种表示方式

1
2
3
4
5
git bundle create awesome-cheatsheets.bundle HEAD~10
git bundle create awesome-cheatsheets.bundle HEAD~10..HEAD
git bundle create awesome-cheatsheets.bundle lhs_commit_md5..rhs_commit_md5
git bundle create awesome-cheatsheets.bundle origin/master..master
git bundle create awesome-cheatsheets.bundle master ^origin/master

子模块

1
git submodule foreach git pull            #子模块更新

其他配置

配置颜色

1
git config --global color.ui true         #显示颜色

配置别名

1
2
3
git config [--global] alias.<alias> '<original command>'    #为所有工作区/当前工作区配置别名
.git/config                               #当前工作区的配置文件
~/.gitconfig                              #当前用户的配置文件

.gitignore

配置文件

vim .gitignore

1
2
3
/<dir name>/                              #忽略文件夹
*.zip                                     #忽略 .zip 文件
/<dir name>/<file name>                   #忽略指定文件

文件生效后

1
2
git add -f <file>                         #强制添加
git check-ignore -v <file>                #查看生效规则

References

Andy
Welcome to andy blog
目录
相关文章
Git 服务器安装
安装 git 1 apt-get install git 创建 git 专用用户 创建用户 git (如果希望多个账户密码可以添加一个组,然后再创建不同的用户) 1
2016-5-26
Core Dump
Core Dump 设置 生成 core 默认是不会产生 core 文件的 1 ulimit -c unlimited # -c 指定 core 文件的大小,unlimited 表示不限制 core 文件
2017-12-21
GDB
帮助信息 1 2 3 4 5 6 7 help # 列出命令分类 help running # 查看某个类别的帮助信息 help run # 查看命令 run 的帮助 help info # 列出查
2017-12-10
Vim
光标移动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
2016-3-2
JavaScript
基础知识 类型 基本类型 最新的 ECMAScript 标准定义了 8 种数据类型,分别是 string number bigint boolean null undefined symbol (ECMAScript 2016新增) 所有基本类型
2016-2-26
Go
安装 前往 官网 下载 go1.19.4.linux-amd64.tar.gz 1 2 3 tar -C /usr/local/ -xzf go1.19.4.linux-amd64.tar.gz export PATH=$PATH:/usr/local/go/bin go version 看到版本号代表 go 安装成功 编译器命令 1 2 3 4 5 6 7 8 9 10 11 12
2019-12-30
Redis
启动 Redis 1 2 3 4 redis-server /path/redis.conf # 指定配置文件启动 redis redis-cli # 开启 redis 客户端 systemctl restart redis.service # 重启 redis systemctl status redis # 检查 redis 运行状态 字符串 1 2
2019-12-24
C#
数据类型 类型 大小 举例 String 2 bytes/char s = “reference” bool 1 byte b = true char 2 bytes ch = ‘a’ byte 1 byte b = 0x78 short 2 bytes val = 70 int 4 bytes val = 700 long 8 bytes val
2019-7-13
Python
常规 Python 对大小写敏感 Python 的索引从 0 开始 Python 使用空白符(制表符或空格)来缩进代码,而不是使用花括号 帮助 获取主
2018-10-6
Nginx
Nginx 常用命令 官方文档 1 2 3 4 5 sudo nginx -t # 检测配置文件是否有错误 sudo systemctl status nginx # nginx 当前的运行状态 sudo systemctl reload nginx # 重新加
2018-2-12