├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── cheatsheet.md ├── git.png ├── git.svg ├── idoc.yml └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.md linguist-detectable=true 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: jaywcjlove 2 | buy_me_a_coffee: jaywcjlove 3 | custom: ["https://www.paypal.me/kennyiseeyou", "https://jaywcjlove.github.io/#/sponsor"] 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/setup-node@v4 13 | with: 14 | node-version: 20 15 | registry-url: 'https://registry.npmjs.org' 16 | 17 | - run: npm install 18 | - run: npm run build 19 | 20 | - name: Generate Contributors Images 21 | uses: jaywcjlove/github-action-contributors@main 22 | with: 23 | filter-author: (renovate\[bot\]|renovate-bot|dependabot\[bot\]) 24 | output: dist/CONTRIBUTORS.svg 25 | avatarSize: 42 26 | 27 | - name: Deploy 28 | uses: peaceiris/actions-gh-pages@v4 29 | with: 30 | github_token: ${{ secrets.GITHUB_TOKEN }} 31 | publish_dir: ./dist -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | 4 | npm-debug.log* 5 | lerna-debug.log 6 | yarn-error.log 7 | package-lock.json 8 | 9 | 10 | .DS_Store 11 | .cache 12 | .vscode 13 | .idea 14 | 15 | *.bak 16 | *.tem 17 | *.temp 18 | #.swp 19 | *.*~ 20 | ~*.* 21 | 22 | # IDEA 23 | *.iml 24 | *.ipr 25 | *.iws 26 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Git Tips 3 | === 4 | 5 | 6 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) 7 | [![Gitee Tips](https://jaywcjlove.github.io/sb/ico/gitee.svg)](https://jaywcjlove.gitee.io/git-tips/) 8 | [![CI](https://github.com/jaywcjlove/git-tips/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/git-tips/actions/workflows/ci.yml) 9 | 10 | 一些使用技巧和笔记笔记,记录一些 git 常用和一些记不住的命令,这个笔记原本是基于 [颜海镜的文章](http://yanhaijing.com/git/2014/11/01/my-git-note)增加的,后面慢慢增加了许多内容,独立一个仓库维护,方便查询和使用。 11 | 12 | 13 | 目录 14 | === 15 | 16 | 17 | 18 | - [入门备忘清单](./cheatsheet.md) 19 | - [安装卸载](#安装卸载) 20 | - [配置管理](#配置管理) 21 | - [不常见的使用场景](#不常见的使用场景) 22 | - [忽略文件的权限变化](#忽略文件的权限变化) 23 | - [设置大小写敏感](#设置大小写敏感) 24 | - [配置自动换行](#配置自动换行) 25 | - [创建SSH密钥](#创建ssh密钥) 26 | - [多账号ssh配置](#多账号ssh配置) 27 | - [免密码登录远程服务器](#免密码登录远程服务器) 28 | - [https协议下提交代码免密码](#https协议下提交代码免密码) 29 | - [文件推向3个git库](#文件推向3个git库) 30 | - [修改远程仓库地址](#修改远程仓库地址) 31 | - [撤销远程记录](#撤销远程记录) 32 | - [放弃本地的文件修改](#放弃本地的文件修改) 33 | - [最简单放弃本地修改内容](#最简单放弃本地修改内容) 34 | - [回退到某一个版本](#回退到某一个版本) 35 | - [搜索 commit 历史记录](#搜索-commit-历史记录) 36 | - [回滚到某个commit提交](#回滚到某个commit提交) 37 | - [去掉某个commit](#去掉某个commit) 38 | - [把 A 分支的某一个 commit,放到 B 分支上](#把-a-分支的某一个-commit放到-b-分支上) 39 | - [获取最近一次提交的 commit id](#获取最近一次提交的-commit-id) 40 | - [两个 git 仓库合并](#两个-git-仓库合并) 41 | - [合并多个commit](#合并多个commit) 42 | - [修改远程Commit记录](#修改远程commit记录) 43 | - [利用commit关闭一个issue](#利用commit关闭一个issue) 44 | - [新建一个空分支](#新建一个空分支) 45 | - [添加忽略文件](#添加忽略文件) 46 | - [忽略某个文件的改动](#忽略某个文件的改动) 47 | - [同步fork的上游仓库](#同步fork的上游仓库) 48 | - [手动合并冲突的 Pull Request](#手动合并冲突的-pull-request) 49 | - [修改作者名](#修改作者名) 50 | - [批量修改历史commit中的名字和邮箱](#批量修改历史commit中的名字和邮箱) 51 | - [查看两个星期内的改动](#查看两个星期内的改动) 52 | - [查看某个文件历史](#查看某个文件历史) 53 | - [查看git仓库中最近修改的分支](#查看git仓库中最近修改的分支) 54 | - [更新所有本地分支](#更新所有本地分支) 55 | - [打造自己的git命令](#打造自己的git命令) 56 | - [删除已经合并到 master 的分支](#删除已经合并到-master-的分支) 57 | - [中文乱码的解决方案](#中文乱码的解决方案) 58 | - [提交一个空文件夹](#提交一个空文件夹) 59 | - [新建仓库](#新建仓库) 60 | - [init](#init) 61 | - [status](#status) 62 | - [add](#add) 63 | - [commit](#commit) 64 | - [remote](#remote) 65 | - [push](#push) 66 | - [clone](#clone) 67 | - [本地](#本地) 68 | - [help](#help) 69 | - [add](#add-1) 70 | - [rm](#rm) 71 | - [commit](#commit-1) 72 | - [reset](#reset) 73 | - [revert](#revert) 74 | - [checkout](#checkout) 75 | - [diff](#diff) 76 | - [stash](#stash) 77 | - [merge](#merge) 78 | - [cherry-pick](#cherry-pick) 79 | - [rebase](#rebase) 80 | - [分支branch](#分支branch) 81 | - [删除](#删除) 82 | - [提交](#提交) 83 | - [拉取](#拉取) 84 | - [分支合并](#分支合并) 85 | - [重命名](#重命名) 86 | - [查看](#查看) 87 | - [新建](#新建) 88 | - [连接](#连接) 89 | - [分支切换](#分支切换) 90 | - [远端](#远端) 91 | - [submodule](#submodule) 92 | - [更新 submodule](#更新-submodule) 93 | - [删除 submodule](#删除-submodule) 94 | - [转换分支](#转换分支) 95 | - [删除文件](#删除文件) 96 | - [remote](#remote-1) 97 | - [标签tag](#标签tag) 98 | - [重命名Tag](#重命名tag) 99 | - [日志log](#日志log) 100 | - [重写历史](#重写历史) 101 | - [其它](#其它) 102 | - [报错问题解决](#报错问题解决) 103 | - [参考资料](#参考资料) 104 | 105 | 106 | 107 | 108 | ## 安装卸载 109 | 110 | [官方教程](https://git-scm.com/download/linux),在 Linux/Unix 系统中,通过工具在中安装 `git`,这种方式比较简单,便于升级卸载工具。 111 | 112 | 下面介绍在 CentOS 系统中,通过 yum 来安装 git 113 | 114 | > **Red Hat Enterprise Linux, Oracle Linux, CentOS, Scientific Linux, et al.** 115 | > RHEL and derivatives typically ship older versions of git. You can [download a tarball](https://www.kernel.org/pub/software/scm/git/) and build from source, or use a 3rd-party repository such as [the IUS Community Project](https://ius.io/) to obtain a more recent version of git. 116 | 117 | 官方文档说 git 在 `RHEL` 和衍生产品通常都会发布旧版本的 `git`,我们需要源码编译安装,或者使用第三方存储库(如[IUS社区项目](https://ius.io/))。 118 | 119 | 现在我们通过,[IUS社区](https://ius.io/GettingStarted/)下载 [ius-release.rpm](https://centos7.iuscommunity.org/ius-release.rpm) 文件进行安装 120 | 121 | ```bash 122 | # 注意下载不同的版本,本机 CentOS 7 123 | wget https://centos7.iuscommunity.org/ius-release.rpm 124 | # 安装rpm文件 125 | rpm -ivh ius-release.rpm 126 | ``` 127 | 128 | 查看可安装的git安装包 129 | 130 | ```bash 131 | repoquery --whatprovides git 132 | # git-0:1.8.3.1-13.el7.x86_64 133 | # git2u-0:2.16.5-1.ius.centos7.x86_64 134 | # git2u-0:2.16.2-1.ius.centos7.x86_64 135 | # git2u-0:2.16.4-1.ius.centos7.x86_64 136 | # git-0:1.8.3.1-14.el7_5.x86_64 137 | ``` 138 | 139 | **yum 卸载 git 安装新版本** 140 | 141 | 卸载 `1.8.3` 的 `git`,安装 `2.16.5` 的 `git` 142 | 143 | ```bash 144 | # 卸载老的版本 145 | yum remove git 146 | # 安装新的版本 147 | yum install git2u 148 | ``` 149 | 150 | ## 配置管理 151 | 152 | 首先是配置帐号信息 `ssh -T git@github.com` 测试。 153 | 154 | ```bash 155 | git help config # 获取帮助信息,查看修改个人信息的参数 156 | git config --list # 查看配置的信息 157 | git config --global user.name "小弟调调" # 修改全局名字 158 | git config --global user.email "wowohoo@qq.com" # 修改全局邮箱 159 | git config --global --unset # 删除全局设置 160 | ``` 161 | 162 | ## 不常见的使用场景 163 | 164 | ### 忽略文件的权限变化 165 | 166 | 不再将文件的权限变化视作改动 167 | 168 | ```bash 169 | git config core.fileMode false 170 | ``` 171 | 172 | ### 设置大小写敏感 173 | 174 | ```bash 175 | git config --get core.ignorecase # 查看git 的设置 176 | git config core.ignorecase false # 设置大小写敏感 177 | git rm -r --cached <目录/文件> # 远程有俩相同目录,通过这种方式清除掉,然后提交记录 178 | ``` 179 | 180 | ### 配置自动换行 181 | 182 | 自动转换坑太大,提交到git是自动将换行符转换为lf 183 | 184 | ```bash 185 | git config --global core.autocrlf input 186 | ``` 187 | 188 | ### 创建SSH密钥 189 | 190 | 这个密钥用来跟 github 通信,在本地终端里生成然后上传到 github 191 | 192 | ```bash 193 | ssh-keygen -t rsa -C 'wowohoo@qq.com' # 生成密钥 194 | ssh-keygen -t rsa -C "wowohoo@qq.com" -f ~/.ssh/ww_rsa # 指定生成目录文件名字 195 | ssh -T git@github.com # 测试是否成功 196 | ``` 197 | 198 | ### 多账号ssh配置 199 | 200 | **1.生成指定名字的密钥** 201 | 202 | `ssh-keygen -t rsa -C "邮箱地址" -f ~/.ssh/jslite_rsa` 203 | 会生成 `jslite_rsa` 和 `jslite_rsa.pub` 这两个文件 204 | 205 | **2.密钥复制到托管平台上** 206 | 207 | `vim ~/.ssh/jslite_rsa.pub` 208 | 打开公钥文件 `jslite_rsa.pub` ,并把内容复制至代码托管平台上 209 | 210 | **3.修改config文件** 211 | 212 | `vim ~/.ssh/config` #修改config文件,如果没有创建 `config` 213 | 214 | ```shell 215 | Host jslite.github.com 216 | HostName github.com 217 | User git 218 | IdentityFile ~/.ssh/jslite_rsa 219 | 220 | Host work.github.com 221 | HostName github.com 222 | # Port 服务器open-ssh端口(默认:22,默认时一般不写此行) 223 | # PreferredAuthentications 配置登录时用什么权限认证 224 | # publickey|password publickey|keyboard-interactive等 225 | User git 226 | IdentityFile ~/.ssh/work_rsa 227 | ``` 228 | 229 | - `Host` 这里是个别名可以随便命名 230 | - `HostName` 一般是网站如:`git@ss.github.com:username/repo.git` 填写 `github.com` 231 | - `User` 通常填写`git` 232 | - `IdentityFile` 使用的公钥文件地址 233 | 234 | **4.测试** 235 | 236 | ```bash 237 | ssh -T git@jslite.github.com # `@`后面跟上定义的Host 238 | ssh -T work.github.com # 通过别名测试 239 | ssh -i ~/公钥文件地址 Host别名 # 如 ssh -i ~/.ssh/work_rsa work.github.com 240 | ``` 241 | 242 | **5.使用** 243 | 244 | ```bash 245 | # 原来的写法 246 | git clone git@github.com:/learngit.git 247 | # 现在的写法 248 | git clone git@jslite.github.com:/learngit.git 249 | git clone git@work.github.com:/learngit.git 250 | ``` 251 | 252 | **5.注意** 253 | 254 | 如果你修改了id_rsa的名字,你需要将ssh key添加到SSH agent中,如: 255 | 256 | ```bash 257 | ssh-add ~/.ssh/jslite_rsa 258 | ssh-add -l # 查看所有的key 259 | ssh-add -D # 删除所有的key 260 | ssh-add -d ~/.ssh/jslite_rsa # 删除指定的key 261 | ``` 262 | 263 | ### 免密码登录远程服务器 264 | 265 | ```bash 266 | $ ssh-keygen -t rsa -P '' -f ~/.ssh/aliyunserver.key 267 | $ ssh-copy-id -i ~/.ssh/aliyunserver.key.pub root@192.168.182.112 # 这里需要输入密码一次 268 | ``` 269 | 270 | 编辑 `~/.ssh/config` 271 | 272 | ```bash 273 | Host aliyun1 274 | HostName 192.168.182.112 275 | User root 276 | PreferredAuthentications publickey 277 | IdentityFile ~/.ssh/aliyunserver.key 278 | ``` 279 | 280 | 上面配置完了,可以通过命令登录,不需要输入IP地址和密码 `ssh aliyun1` 281 | 282 | ### https协议下提交代码免密码 283 | 284 | ```bash 285 | git clone https://github.com/username/rep.git 286 | ``` 287 | 288 | 通过上面方式克隆可能需要密码,解决办法:进入当前克隆的项目 `vi rep/.git/config` 编辑 `config`, 按照下面方式修改,你就可以提交代码不用输入密码了。 289 | 290 | ```diff 291 | [core] 292 | repositoryformatversion = 0 293 | filemode = true 294 | bare = false 295 | logallrefupdates = true 296 | ignorecase = true 297 | precomposeunicode = true 298 | [remote "origin"] 299 | - url = https://github.com/username/rep.git 300 | + url = https://用户名:密码@github.com/username/rep.git 301 | fetch = +refs/heads/*:refs/remotes/origin/* 302 | [branch "master"] 303 | remote = origin 304 | merge = refs/heads/master 305 | ``` 306 | 307 | ### 文件推向3个git库 308 | 309 | **1. 增加3个远程库地址** 310 | 311 | ```shell 312 | git remote add origin https://github.com/JSLite/JSLite.git 313 | git remote set-url --add origin https://gitlab.com/wang/JSLite.js.git 314 | git remote set-url --add origin https://oschina.net/wang/JSLite.js.git 315 | ``` 316 | 317 | **2. 删除其中一个 set-url 地址** 318 | 319 | ```shell 320 | usage: git remote set-url [--push] [] 321 | or: git remote set-url --add 322 | or: git remote set-url --delete 323 | ``` 324 | 325 | `git remote set-url --delete origin https://oschina.net/wang/JSLite.js.git` 326 | 327 | **3.推送代码** 328 | 329 | ```bash 330 | git push origin master 331 | git push -f origin master # 强制推送 332 | ``` 333 | 334 | **4.拉代码** 335 | 336 | 只能拉取 `origin` 里的一个url地址,这个fetch-url 337 | 默认为你添加的到 `origin`的第一个地址 338 | 339 | ```shell 340 | git pull origin master 341 | git pull --all # 获取远程所有内容包括tag 342 | git pull origin next:master # 取回origin主机的next分支,与本地的master分支合并 343 | git pull origin next # 远程分支是与当前分支合并 344 | 345 | # 上面一条命令等同于下面两条命令 346 | git fetch origin 347 | git merge origin/next 348 | ``` 349 | 350 | 如果远程主机删除了某个分支,默认情况下,git pull 不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,由于其他人操作了远程主机,导致git pull不知不觉删除了本地分支。 351 | 但是,你可以改变这个行为,加上参数 -p 就会在本地删除远程已经删除的分支。 352 | 353 | ```shell 354 | $ git pull -p 355 | # 等同于下面的命令 356 | $ git fetch --prune origin 357 | $ git fetch -p 358 | ``` 359 | 360 | **5.更改pull** 361 | 362 | 只需要更改config文件里,那三个url的顺序即可,fetch-url会直接对应排行第一的那个utl连接。 363 | 364 | 365 | ### 修改远程仓库地址 366 | 367 | ```bash 368 | git remote remove origin # 删除该远程路径 369 | git remote add origin git@jslite.github.com:JSLite/JSLite.git # 添加远程路径 370 | ``` 371 | 372 | ### 撤销远程记录 373 | 374 | ```shell 375 | git reset --hard HEAD~1 # 撤销一条记录 376 | git push -f origin HEAD:master # 同步到远程仓库 377 | ``` 378 | 379 | ### 放弃本地的文件修改 380 | 381 | ```shell 382 | git reset --hard FETCH_HEAD # FETCH_HEAD表示上一次成功git pull之后形成的commit点。然后git pull 383 | ``` 384 | 385 | `git reset --hard FETCH_HEAD` 出现错误 386 | 387 | ```bash 388 | git pull 389 | You are not currently on a branch, so I cannot use any 390 | 'branch..merge' in your configuration file. 391 | Please specify which remote branch you want to use on the command 392 | line and try again (e.g. 'git pull '). 393 | See git-pull(1) FOR details. 394 | ``` 395 | 396 | 解决方法: 397 | 398 | ```bash 399 | git checkout -b temp # 新建+切换到temp分支 400 | git checkout master 401 | ``` 402 | 403 | ### 最简单放弃本地修改内容 404 | 405 | ```bash 406 | # 如果有的修改以及加入暂存区的话 407 | git reset --hard 408 | # 还原所有修改,不会删除新增的文件 409 | git checkout . 410 | # 下面命令会删除新增的文件 411 | git clean -xdf 412 | ``` 413 | 414 | 通过存储暂存区stash,在删除暂存区的方法放弃本地修改。 415 | 416 | ```bash 417 | git stash && git stash drop 418 | ``` 419 | 420 | ### 回退到某一个版本 421 | 422 | ```bash 423 | git reset --hard 424 | # 例如 git reset --hard a3hd73r 425 | # --hard代表丢弃工作区的修改,让工作区与版本代码一模一样,与之对应, 426 | # --soft参数代表保留工作区的修改。 427 | ``` 428 | 429 | ### 搜索 commit 历史记录 430 | 431 | ```shell 432 | git log --grep=224 433 | # 这条命令是查看含有 "224" 关键字的 git commit 434 | ``` 435 | 436 | ### 回滚到某个commit提交 437 | 438 | ```shell 439 | git revert HEAD~1 # 撤销一条记录 会弹出 commit 编辑 440 | git push # 提交回滚 441 | ``` 442 | 443 | ### 去掉某个commit 444 | 445 | ```bash 446 | # 实质是新建了一个与原来完全相反的commit,抵消了原来commit的效果 447 | git revert 448 | ``` 449 | 450 | ### 把 A 分支的某一个 commit,放到 B 分支上 451 | 452 | 对两个分支,同时都拥有的文件,进行修改后,再同时 `commit` 到这两个分支,比如 `master` 分支和 `branch1` 分支,都拥有文件 `test.js` ,在 `master` 或者 `branch1` 分支下对 `test.js` 进行修改后,把修改的 `test.js` 同时提交到 `master` 分支和 `branch1` 分支。 453 | 454 | ```bash 455 | git checkout && git cherry-pick 456 | ``` 457 | 458 | ### 获取最近一次提交的 commit id 459 | 460 | ```bash 461 | git rev-parse HEAD # e10721cb8859b2cd340d31a52ef4bf4b9629ddda 462 | git rev-parse --short HEAD # e10721c 463 | ``` 464 | 465 | ### 两个 git 仓库合并 466 | 467 | 现在有两个仓库 [kktjs/kkt](https://github.com/kktjs/kkt.git) 和 [kktjs/kkt-next](https://github.com/kktjs/kkt-next.git) 我们需要将 `kkt-next` 仓库合并到 `kkt` 并保留 `kkt-next` 的所有提交内容。 468 | 469 | ```bash 470 | # 1. 克隆主仓库代码 471 | git clone git@github.com:kktjs/kkt.git 472 | # 2. 将 kkt-next 作为远程仓库,添加到 kkt 中,设置别名为 other 473 | git remote add other git@github.com:kktjs/kkt-next.git 474 | # 3. 从 kkt-next 仓库中拉取数据到本仓库 475 | git fetch other 476 | # 4. 将 kkt-next 仓库拉取的 master 分支作为新分支 checkout 到本地,新分支名设定为 kkt-next 477 | git checkout -b kkt-next other/master 478 | # 5. 切换回 kkt 的 master 分支 479 | git checkout master 480 | # 6. 将 kkt-next 合并入 kkt 的 master 分支 481 | git merge kkt-next 482 | # 如果第 6 步报错 `fatal: refusing to merge unrelated histories` 483 | # 请执行下面命令 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 484 | git merge kkt-next --allow-unrelated-histories 485 | ``` 486 | 487 | 在合并时有可能两个分支对同一个文件都做了修改,这时需要解决冲突,对文本文件来说很简单,根据需要对冲突的位置进行处理就可以。对于二进制文件,需要用到如下命令: 488 | 489 | ```bash 490 | git checkout --theirs YOUR_BINARY_FILES # 保留需要合并进来的分支的修改 491 | git checkout --ours YOUR_BINARY_FILES # 保留自己的修改 492 | git add YOUR_BINARY_FILES 493 | ``` 494 | 495 | ### 合并多个commit 496 | 497 | ```bash 498 | # 这个命令,将最近4个commit合并为1个,HEAD代表当前版本。 499 | # 将进入VIM界面,你可以修改提交信息。 500 | git rebase -i HEAD~4 501 | # 可以看到其中分为两个部分,上方未注释的部分是填写要执行的指令, 502 | # 而下方注释的部分则是指令的提示说明。指令部分中由前方的命令名称、commit hash 和 commit message 组成 503 | # 当前我们只要知道 pick 和 squash 这两个命令即可。 504 | # --> pick 的意思是要会执行这个 commit 505 | # --> squash 的意思是这个 commit 会被合并到前一个commit 506 | 507 | # 我们将 需要保留的 这个 commit 前方的命令改成 squash 或 s,然后输入:wq以保存并退出 508 | # 这是我们会看到 commit message 的编辑界面 509 | 510 | # 其中, 非注释部分就是两次的 commit message, 你要做的就是将这两个修改成新的 commit message。 511 | # 512 | # 输入wq保存并推出, 再次输入git log查看 commit 历史信息,你会发现这两个 commit 已经合并了。 513 | # 将修改强制推送到前端 514 | git push -f origin master 515 | ``` 516 | 517 | ### 修改远程Commit记录 518 | 519 | ```bash 520 | git commit --amend 521 | # amend只能修改没有提交到线上的,最后一次commit记录 522 | git rebase -i HEAD~3 523 | # 表示要修改当前版本的倒数第三次状态 524 | # 将要更改的记录行首单词 pick 改为 edit 525 | pick 96dc3f9 doc: Update quick-start.md 526 | pick f1cce8a test(Transition):Add transition test (#47) 527 | pick 6293516 feat(Divider): Add Divider component. 528 | # Rebase eeb03a4..6293516 onto eeb03a4 (3 commands) 529 | # 530 | # Commands: 531 | # p, pick = use commit 532 | # r, reword = use commit, but edit the commit message 533 | # e, edit = use commit, but stop for amending 534 | # s, squash = use commit, but meld into previous commit 535 | # f, fixup = like "squash", but discard this commit's log message 536 | # x, exec = run command (the rest of the line) using shell 537 | # d, drop = remove commit 538 | ``` 539 | 540 | 保存并退出,会弹出下面提示 541 | 542 | ```bash 543 | # You can amend the commit now, with 544 | # 545 | # git commit --amend 546 | # 547 | # Once you are satisfied with your changes, run 548 | # 549 | # git rebase --continue 550 | 551 | # 通过这条命令进入编辑页面更改commit,保存退出 552 | git commit --amend 553 | # 保存退出确认修改,继续执行 rebase, 554 | git rebase --continue 555 | # 如果修改多条记录反复执行上面两条命令直到完成所有修改 556 | 557 | # 最后,确保别人没有提交进行push,最好不要加 -f 强制推送 558 | git push -f origin master 559 | ``` 560 | 561 | ### 利用commit关闭一个issue 562 | 563 | 这个功能在Github上可以玩儿,Gitlab上特别老的版本不能玩儿哦,那么如何跟随着commit关闭一个issue呢? 在confirm merge的时候可以使用一下命令来关闭相关issue: 564 | 565 | `fixes #xxx`、 `fixed #xxx`、 `fix #xxx`、 `closes #xxx`、 `close #xxx`、 `closed #xxx`、 566 | 567 | ### 新建一个空分支 568 | 569 | ```bash 570 | # 这种方式新建的分支(gh-pages)是没有 commit 记录的 571 | git checkout --orphan gh-pages 572 | # 删除新建的gh-pages分支原本的内容,如果不删除,提交将作为当前分支的第一个commit 573 | git rm -rf . 574 | # 查看一下状态 有可能上面一条命令,没有删除还没有提交的的文件 575 | git state 576 | ``` 577 | 578 | ### 添加忽略文件 579 | 580 | ``` 581 | echo node_modules/ >> .gitignore 582 | ``` 583 | 584 | ### 忽略某个文件的改动 585 | 586 | ```bash 587 | git update-index --assume-unchanged path/to/file # 关闭 track 指定文件的改动,也就是 Git 将不会在记录这个文件的改动 588 | git update-index --no-assume-unchanged path/to/file # 恢复 track 指定文件的改动 589 | ``` 590 | 591 | ### 同步fork的上游仓库 592 | 593 | [Github教程同步fork教程](https://help.github.com/articles/syncing-a-fork/),[在Github上同步一个分支(fork)](http://www.miss77.net/549.html) 594 | 595 | **设置添加多个远程仓库地址。** 596 | 597 | 在同步之前,需要创建一个远程点指向上游仓库(repo).如果你已经派生了一个原始仓库,可以按照如下方法做。 598 | 599 | ```shell 600 | $ git remote -v 601 | # List the current remotes (列出当前远程仓库) 602 | # origin https://github.com/user/repo.git (fetch) 603 | # origin https://github.com/user/repo.git (push) 604 | $ git remote add upstream https://github.com/otheruser/repo.git 605 | # Set a new remote (设置一个新的远程仓库) 606 | $ git remote -v 607 | # Verify new remote (验证新的原唱仓库) 608 | # origin https://github.com/user/repo.git (fetch) 609 | # origin https://github.com/user/repo.git (push) 610 | # upstream https://github.com/otheruser/repo.git (fetch) 611 | # upstream https://github.com/otheruser/repo.git (push) 612 | ``` 613 | 614 | **同步更新仓库内容** 615 | 616 | 同步上游仓库到你的仓库需要执行两步:首先你需要从远程拉去,之后你需要合并你希望的分支到你的本地副本分支。从上游的存储库中提取分支以及各自的提交内容。 `master` 将被存储在本地分支机构 `upstream/master` 617 | 618 | ```shell 619 | git fetch upstream 620 | # remote: Counting objects: 75, done. 621 | # remote: Compressing objects: 100% (53/53), done. 622 | # remote: Total 62 (delta 27), reused 44 (delta 9) 623 | # Unpacking objects: 100% (62/62), done. 624 | # From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY 625 | # * [new branch] master -> upstream/master 626 | ``` 627 | 628 | 检查你的 fork's 本地 `master` 分支 629 | 630 | ```shell 631 | git checkout master 632 | # Switched to branch 'master' 633 | ``` 634 | 635 | 合并来自 `upstream/master` 的更改到本地 master 分支上。 这使你的前 fork's `master` 分支与上游资源库同步,而不会丢失你本地修改。 636 | 637 | ```shell 638 | git merge upstream/master 639 | # Updating a422352..5fdff0f 640 | # Fast-forward 641 | # README | 9 ------- 642 | # README.md | 7 ++++++ 643 | # 2 files changed, 7 insertions(+), 9 deletions(-) 644 | # delete mode 100644 README 645 | # create mode 100644 README.md 646 | ``` 647 | 648 | ### 手动合并冲突的 Pull Request 649 | 650 | 以 [tsbbjs/tsbb](https://github.com/tsbbjs/tsbb) 为例,合并来自 [jaywcjlove/tsbb](https://github.com/jaywcjlove/tsbb) master分支的 `Pull Request`。 651 | 652 | ```bash 653 | # 1. 克隆主仓库 654 | git clone git@github.com:tsbbjs/tsbb.git 655 | # 2. 在主仓库 master 分支切个 jaywcjlove-master 分支出来,并且切换到 jaywcjlove-master 分支 656 | git checkout -b jaywcjlove-master master 657 | # 3. 获取 jaywcjlove/tsbb 仓库 master 分支最新代码 658 | git pull https://github.com/jaywcjlove/tsbb.git master 659 | # ⚠️ 注意下面是输出内容: 660 | # ---------------------- 661 | # Auto-merging src/babel/transform.ts 662 | # CONFLICT (content): Merge conflict in src/babel/transform.ts 663 | # ---------------------- 664 | # ⚠️ 注意上面 CONFLICT 标识是有冲突无法自动合并的代码,根据路径进入代码手动合并 665 | # 4. 合并完成之后,进行 commit 说明合并内容 666 | git commit -m "Merge branch 'master' of github.com:jaywcjlove/tsbb #3" 667 | # 5. 切换到 master 分支,如果是 PR 其它分支,这里就切其它分支 668 | git checkout master 669 | # 6. 合并 jaywcjlove-master 分支的代码 670 | git merge --no-ff jaywcjlove-master 671 | # 7. 提交代码 672 | git push origin master 673 | ``` 674 | 675 | ### 修改作者名 676 | 677 | ``` 678 | git commit --amend --author='Author Name ' 679 | ``` 680 | 681 | ### 批量修改历史commit中的名字和邮箱 682 | 683 | 这是 [Github官方教程](https://help.github.com/articles/changing-author-info/) 684 | 685 | **1.克隆仓库** 686 | 687 | 注意参数,这个不是普通的clone,clone下来的仓库并不能参与开发 688 | 689 | ```bash 690 | git clone --bare https://github.com/user/repo.git 691 | cd repo.git 692 | ``` 693 | 694 | **2.命令行中运行代码** 695 | 696 | OLD_EMAIL原来的邮箱 697 | CORRECT_NAME更正的名字 698 | CORRECT_EMAIL更正的邮箱 699 | 700 | 将下面代码复制放到命令行中执行 701 | 702 | ```bash 703 | git filter-branch -f --env-filter ' 704 | OLD_EMAIL="wowohoo@qq.com" 705 | CORRECT_NAME="小弟调调" 706 | CORRECT_EMAIL="更正的邮箱@qq.com" 707 | if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ] 708 | then 709 | export GIT_COMMITTER_NAME="$CORRECT_NAME" 710 | export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL" 711 | fi 712 | if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ] 713 | then 714 | export GIT_AUTHOR_NAME="$CORRECT_NAME" 715 | export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL" 716 | fi 717 | ' --tag-name-filter cat -- --branches --tags 718 | ``` 719 | 720 | 执行过程 721 | 722 | ```bash 723 | Rewrite 160d4df2689ff6df3820563bfd13b5f1fb9ba832 (479/508) (16 seconds passed, remaining 0 predicted) 724 | Ref 'refs/heads/dev' was rewritten 725 | Ref 'refs/heads/master' was rewritten 726 | ``` 727 | 728 | **3.同步到远程仓库** 729 | 730 | 同步到push远程git仓库 731 | 732 | ```bash 733 | git push --force --tags origin 'refs/heads/*' 734 | ``` 735 | 736 | 我还遇到了如下面错误,lab默认给master分支加了保护,不允许强制覆盖。`Project(项目)`->`Setting`->`Repository` 菜单下面的`Protected branches`把master的保护去掉就可以了。修改完之后,建议把master的保护再加回来,毕竟强推不是件好事。 737 | 738 | ```bash 739 | remote: GitLab: You are not allowed to force push code to a protected branch on this project. 740 | ``` 741 | 742 | 当上面的push 不上去的时候,先 `git pull` 确保最新代码 743 | 744 | ```bash 745 | git pull --allow-unrelated-histories 746 | # 或者指定分枝 747 | git pull origin master --allow-unrelated-histories 748 | ``` 749 | 750 | **4. 删除仓库** 751 | 752 | ```bash 753 | cd .. 754 | rm -rf repo.git 755 | ``` 756 | 757 | ### 查看两个星期内的改动 758 | 759 | ``` 760 | git whatchanged --since='2 weeks ago' 761 | ``` 762 | 763 | ### 查看某个文件历史 764 | 765 | ```shell 766 | git log --pretty=oneline 文件名 # 列出文件的所有改动历史 767 | git show c178bf49 # 某次的改动的修改记录 768 | git log -p c178bf49 # 某次的改动的修改记录 769 | git blame 文件名 # 显示文件的每一行是在那个版本最后修改。 770 | git whatchanged 文件名 # 显示某个文件的每个版本提交信息:提交日期,提交人员,版本号,提交备注(没有修改细节) 771 | ``` 772 | 773 | ### 查看git仓库中最近修改的分支 774 | 775 | ```bash 776 | git for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)' 777 | ``` 778 | 779 | ### 更新所有本地分支 780 | 781 | ```bash 782 | git branch \ 783 | --format "%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)" | 784 | sh 785 | ``` 786 | 787 | ### 打造自己的git命令 788 | 789 | ```sh 790 | git config --global alias.st status 791 | git config --global alias.br branch 792 | git config --global alias.co checkout 793 | git config --global alias.ci commit 794 | ``` 795 | 796 | 配置好后再输入git命令的时候就不用再输入一大段了,例如我们要查看状态,只需: 797 | 798 | ```sh 799 | git st 800 | ``` 801 | 802 | ### 删除已经合并到 master 的分支 803 | 804 | ```bash 805 | git branch --merged master | grep -v '^\*\| master' | xargs -n 1 git branch -d 806 | ``` 807 | 808 | ### 中文乱码的解决方案 809 | 810 | ```bash 811 | git config --global core.quotepath false 812 | ``` 813 | 814 | ### 提交一个空文件夹 815 | 816 | 在空文件夹中建立一个文件 `.gitkeep`, 你就可以提交这个空文件夹了。 817 | 818 | ## 新建仓库 819 | 820 | ### init 821 | 822 | `git init` #初始化 823 | 824 | ### status 825 | 826 | `git status` #获取状态 827 | 828 | ### add 829 | 830 | `git add file` # .或*代表全部添加 831 | `git rm --cached ` # 在commit之前撤销git add操作 832 | `git reset head` # 好像比上面`git rm --cached`更方便 833 | 834 | ### commit 835 | 836 | `git commit -m "message"` #此处注意乱码 837 | 838 | ### remote 839 | 840 | `git remote add origin git@github.com:JSLite/test.git` #添加源 841 | 842 | ### push 843 | 844 | ```bash 845 | git push -u origin master # push同事设置默认跟踪分支 846 | git push origin master 847 | git push -f origin master # 强制推送文件,缩写 -f(全写--force) 848 | ``` 849 | 850 | ## clone 851 | 852 | ```bash 853 | git clone git://github.com/JSLite/JSLite.js.git 854 | git clone git://github.com/JSLite/JSLite.js.git --depth=1 855 | git clone git://github.com/JSLite/JSLite.js.git mypro # 克隆到自定义文件夹 856 | git clone [user@]example.com:path/to/repo.git/ # SSH协议还有另一种写法。 857 | ``` 858 | 859 | git clone支持多种协议,除了HTTP(s)以外,还支持SSH、Git、本地文件协议等,下面是一些例子。`git clone <版本库的网址> <本地目录名>` 860 | 861 | ```shell 862 | $ git clone http[s]://example.com/path/to/repo.git/ 863 | $ git clone ssh://example.com/path/to/repo.git/ 864 | $ git clone ssh://example.com/path/to/repo.git/ 865 | $ git clone git://example.com/path/to/repo.git/ 866 | $ git clone /opt/git/project.git 867 | $ git clone file:///opt/git/project.git 868 | $ git clone ftp[s]://example.com/path/to/repo.git/ 869 | $ git clone rsync://example.com/path/to/repo.git/ 870 | ``` 871 | 872 | ## 本地 873 | 874 | ### help 875 | 876 | ```bash 877 | git help config # 获取帮助信息 878 | ``` 879 | 880 | ### add 881 | 882 | ```shell 883 | git add * # 跟踪新文件 884 | git add -u [path] # 添加[指定路径下]已跟踪文件 885 | ``` 886 | 887 | ### rm 888 | 889 | ```shell 890 | rm *&git rm * # 移除文件 891 | git rm -f * # 移除文件 892 | git rm --cached * # 取消跟踪 893 | git mv file_from file_to # 重命名跟踪文件 894 | git log # 查看提交记录 895 | ``` 896 | 897 | ### commit 898 | 899 | ```shell 900 | git commit #提交更新 901 | git commit -m 'message' #提交说明 902 | git commit -a #跳过使用暂存区域,把所有已经跟踪过的文件暂存起来一并提交 903 | git commit --amend #修改最后一次提交 904 | git commit log #查看所有提交,包括没有push的commit 905 | git commit -m "#133" #关联issue 任意位置带上# 符号加上issue号码 906 | git commit -m "fix #133" commit关闭issue 907 | git commit -m '概要描述'$'\n\n''1.详细描述'$'\n''2.详细描述' #提交简要描述和详细描述 908 | ``` 909 | 910 | ### reset 911 | 912 | ```shell 913 | git reset HEAD * # 取消已经暂存的文件 914 | git reset --mixed HEAD * # 同上 915 | git reset --soft HEAD * # 重置到指定状态,不会修改索引区和工作树 916 | git reset --hard HEAD * # 重置到指定状态,会修改索引区和工作树 917 | git reset -- files * # 重置index区文件 918 | ``` 919 | 920 | ### revert 921 | 922 | ```shell 923 | git revert HEAD # 撤销前一次操作 924 | git revert HEAD~ # 撤销前前一次操作 925 | git revert commit # 撤销指定操作 926 | ``` 927 | 928 | ### checkout 929 | 930 | ```shell 931 | git checkout -- file # 取消对文件的修改(从暂存区——覆盖worktree file) 932 | git checkout branch|tag|commit -- file_name # 从仓库取出file覆盖当前分支 933 | git checkout HEAD~1 [文件] # 将会更新 working directory 去匹配某次 commit 934 | git checkout -- . # 从暂存区取出文件覆盖工作区 935 | git checkout -b gh-pages 0c304c9 # 这个表示 从当前分支 commit 哈希值为 0c304c9 的节点,分一个新的分支gh-pages出来,并切换到 gh-pages 936 | ``` 937 | 938 | ### diff 939 | 940 | ```shell 941 | git diff file # 查看指定文件的差异 942 | git diff --stat # 查看简单的diff结果 943 | git diff # 比较 Worktree 和 Index 之间的差异 944 | git diff --cached # 比较Index和HEAD之间的差异 945 | git diff HEAD # 比较Worktree和HEAD之间的差异 946 | git diff branch # 比较Worktree和branch之间的差异 947 | git diff branch1 branch2 # 比较两次分支之间的差异 948 | git diff commit commit # 比较两次提交之间的差异 949 | git diff master..test # 上面这条命令只显示两个分支间的差异 950 | git diff master...test # 你想找出‘master’,‘test’的共有 父分支和'test'分支之间的差异,你用3个‘.'来取代前面的两个'.' 951 | ``` 952 | 953 | ### stash 954 | 955 | 存储当前的修改,但不用提交 commit 956 | 957 | ```shell 958 | git stash # 将工作区现场(已跟踪文件)储藏起来,等以后恢复后继续工作。 959 | git stash -u # 保存当前状态,包括 untracked 的文件 960 | git stash list # 查看保存的工作现场 961 | git stash apply # 恢复工作现场 962 | git stash drop # 删除stash内容 963 | git stash clear # 删除所有的 stash 964 | git stash pop # 恢复的同时直接删除stash内容 965 | git stash apply stash@{0} # 恢复指定的工作现场,当你保存了不只一份工作现场时。 966 | git checkout -- # 从 stash 中拿出某个文件的修改 967 | ``` 968 | 969 | ### merge 970 | 971 | ```bash 972 | git merge --squash test # 合并压缩,将test上的commit压缩为一条 973 | ``` 974 | 975 | ### cherry-pick 976 | 977 | ```shell 978 | git cherry-pick commit # 拣选合并,将commit合并到当前分支 979 | git cherry-pick -n commit # 拣选多个提交,合并完后可以继续拣选下一个提交 980 | ``` 981 | 982 | ### rebase 983 | 984 | ```shell 985 | git rebase master # 将master分之上超前的提交,变基到当前分支 986 | git rebase --onto master 169a6 # 限制回滚范围,rebase当前分支从169a6以后的提交 987 | git rebase --interactive # 交互模式,修改commit 988 | git rebase --continue # 处理完冲突继续合并 989 | git rebase --skip # 跳过 990 | git rebase --abort # 取消合并 991 | ``` 992 | 993 | ## 分支branch 994 | 995 | ### 删除 996 | 997 | ```shell 998 | git push origin :branchName # 删除远程分支 999 | git push origin --delete new # 删除远程分支new 1000 | git branch -d branchName # 删除本地分支,强制删除用-D 1001 | git branch -d test # 删除本地test分支 1002 | git branch -D test # 强制删除本地test分支 1003 | git remote prune origin # 远程删除了,本地还能看到远程存在,这条命令删除远程不存在的分支 1004 | ``` 1005 | 1006 | ### 提交 1007 | 1008 | ```bash 1009 | git push -u origin branchName # 提交分支到远程origin主机中 1010 | ``` 1011 | 1012 | ### 拉取 1013 | 1014 | ```bash 1015 | git fetch -p # 拉取远程分支时,自动清理 远程分支已删除,本地还存在的对应同名分支。 1016 | git fetch origin '+refs/heads/*:refs/heads/*' # 更新所有分支内容 1017 | ``` 1018 | 1019 | ### 分支合并 1020 | 1021 | ```shell 1022 | git merge branchName # 合并分支 - 将分支branchName和当前所在分支合并 1023 | git merge origin/master # 在本地分支上合并远程分支。 1024 | git rebase origin/master # 在本地分支上合并远程分支。 1025 | git merge test # 将test分支合并到当前分支 1026 | ``` 1027 | 1028 | ### 重命名 1029 | 1030 | ```bash 1031 | git branch -m old new # 重命名分支 1032 | ``` 1033 | 1034 | ### 查看 1035 | 1036 | ```shell 1037 | git branch # 列出本地分支 1038 | git branch -r # 列出远端分支 1039 | git branch -a # 列出所有分支 1040 | git branch -v # 查看各个分支最后一个提交对象的信息 1041 | git branch --merge # 查看已经合并到当前分支的分支 1042 | git branch --no-merge # 查看为合并到当前分支的分支 1043 | git remote show origin # 可以查看remote地址,远程分支 1044 | ``` 1045 | 1046 | ### 新建 1047 | 1048 | ```shell 1049 | git branch test # 新建test分支 1050 | git branch newBrach 3defc69 # 指定哈希3defc69,新建分支名字为newBrach 1051 | git checkout -b newBrach origin/master # 取回远程主机的更新以后,在它的基础上创建一个新的分支 1052 | git checkout -b newBrach 3defc69 # 以哈希值3defc69,新建 newBrach 分支,并切换到该分支 1053 | ``` 1054 | 1055 | ### 连接 1056 | 1057 | ```shell 1058 | git branch --set-upstream dev origin/dev # 将本地dev分支与远程dev分支之间建立链接 1059 | git branch --set-upstream master origin/next # 手动建立追踪关系 1060 | ``` 1061 | 1062 | ### 分支切换 1063 | 1064 | ```shell 1065 | git checkout - # 快速切换分支上一个分支 1066 | git checkout test # 切换到test分支 1067 | git checkout -b test # 新建+切换到test分支 1068 | git checkout -b test dev # 基于dev新建test分支,并切换 1069 | ``` 1070 | 1071 | ## 远端 1072 | 1073 | ```shell 1074 | git fetch <远程主机名> <分支名> # fetch取回所有分支(branch)的更新 1075 | git fetch origin remotebranch[:localbranch] # 从远端拉去分支[到本地指定分支] 1076 | git merge origin/branch # 合并远端上指定分支 1077 | git pull origin remotebranch:localbranch # 拉去远端分支到本地分支 1078 | git push origin branch # 将当前分支,推送到远端上指定分支 1079 | git push origin localbranch:remotebranch # 推送本地指定分支,到远端上指定分支 1080 | git push origin :remotebranch # 删除远端指定分支 1081 | git checkout -b [--track] test origin/dev # 基于远端dev分支,新建本地test分支[同时设置跟踪] 1082 | ``` 1083 | 1084 | ## submodule 1085 | 1086 | 克隆项目同时克隆 submodule 1087 | 1088 | ```bash 1089 | git clone https://github.com/jaywcjlove/handbook.git --depth=1 --recurse-submodules 1090 | ``` 1091 | 1092 | 克隆项目,之后再手动克隆 submodule 子项目 1093 | 1094 | ```bash 1095 | git submodule add -b gh-pages --force '仓库地址' '路径' 1096 | git submodule add --force '仓库地址' '路径' 1097 | # 其中,仓库地址是指子模块仓库地址,路径指将子模块放置在当前工程下的路径。 1098 | # 注意:路径不能以 / 结尾(会造成修改不生效)、不能是现有工程已有的目录(不能順利 Clone) 1099 | git submodule init # 初始化 submodule 1100 | git submodule update # 更新submodule(必须在根目录执行命令) 1101 | git submodule update --init --recursive # 下载的工程带有submodule 1102 | git submodule update --recursive --remote # 对于 git 1.8.2 或更高版本,添加了选项 --remote 以支持更新远程分支 1103 | git pull --recurse-submodules # 更新 submodule git 1.7.3 版本 1104 | ``` 1105 | 1106 | 当使用`git clone`下来的工程中带有submodule时,初始的时候,submodule的内容并不会自动下载下来的,此时,只需执行如下命令: 1107 | 1108 | ```bash 1109 | git submodule foreach --recursive git submodule init 1110 | ``` 1111 | 1112 | ### 更新 submodule 1113 | 1114 | ```bash 1115 | git submodule foreach git pull # submodule 里有其他的 submodule 一次更新 1116 | git submodule foreach git pull origin master # submodule更新 1117 | git submodule foreach --recursive git submodule update 1118 | git submodule update --recursive --remote 1119 | git pull --recurse-submodules 1120 | git submodule deinit --all -f # 清理 submodule 1121 | ``` 1122 | 1123 | ```bash 1124 | git clone --recurse-submodules --depth=1 --shallow-submodules https://github.com/example/project.git 1125 | # --depth 选项限制拉取历史记录的数量,以减少克隆所需的时间和空间 1126 | # --shallow-submodules 则限制子模块拉取的历史记录数量,这两者的结合可以在 Git 项目中只拉取代码 1127 | ``` 1128 | 1129 | ### 删除 submodule 1130 | 1131 | ```bash 1132 | git ls-files --stage <子项目名称路径> # 查看子项目 1133 | vim .gitmodules # 删除对应的 submodule 1134 | vim .git/config # 删除对应的 submodule 1135 | git rm --cached <子模块名称> # 删除缓存中的子项目,注意没有 `/` 1136 | git rm --cached subProjectName 1137 | rm -rf project/subProjectName 1138 | rm .git/module/* # 删除模块下的子模块目录,每个子模块对应一个目录,注意只删除对应的子模块目录即可 1139 | ``` 1140 | 1141 | ### 转换分支 1142 | 1143 | ```bash 1144 | $ git config -f .gitmodules submodule.public.branch gh-pages 1145 | ``` 1146 | 1147 | 下面是更改 `.gitmodules` 文件内容 1148 | 1149 | ``` 1150 | [submodule "public"] 1151 | path = public 1152 | url = git@github.com:jaywcjlove/gitke.git 1153 | branch = gh-pages 1154 | ``` 1155 | 1156 | ## 删除文件 1157 | 1158 | ```bash 1159 | git rm -rf node_modules/ 1160 | ``` 1161 | 1162 | ## remote 1163 | 1164 | git是一个分布式代码管理工具,所以可以支持多个仓库,在git里,服务器上的仓库在本地称之为remote。个人开发时,多源用的可能不多,但多源其实非常有用。 1165 | 1166 | ```shell 1167 | git remote add origin1 git@github.com:yanhaijing/data.js.git 1168 | git remote # 显示全部源 1169 | git remote -v # 显示全部源+详细信息 1170 | git remote rename origin1 origin2 # 重命名 1171 | git remote rm origin # 删除 1172 | git remote show origin # 查看指定源的全部信息 1173 | ``` 1174 | 1175 | ## 标签tag 1176 | 1177 | 当开发到一定阶段时,给程序打标签是非常棒的功能。 1178 | 1179 | ```bash 1180 | git tag -a v0.1.1 9fbc3d0 # 补打 tag,根据 hash 创建 tag 1181 | git tag -a v0.1 -m 'my version 1.4' # 新建带注释标签 1182 | git push origin --tags # 一次性推送所有分支 1183 | git push origin v1.5 # 推送单个tag到orgin源上 1184 | git tag -v v1.4.2.1 # 验证标签,验证已经签署的标签 1185 | git show v1.5 # 看到对应的 GPG 签 1186 | 1187 | git tag # 列出现有标签 1188 | git tag v0gi.1 # 新建标签 1189 | git checkout tagname # 切换到标签 1190 | git tag -d v0.1 # 删除标签 1191 | git push origin :refs/tags/v0.1 # 删除远程标签 1192 | git pull --all # 获取远程所有内容包括tag 1193 | git --git-dir='<绝对地址>/.git' describe --tags HEAD # 查看本地版本信息 1194 | ``` 1195 | 1196 | ### 重命名Tag 1197 | 1198 | ```bash 1199 | mv .git/refs/tags/1.9.1 .git/refs/tags/v1.9.1 1200 | git push -f --tags 1201 | ``` 1202 | 1203 | ## 日志log 1204 | 1205 | ```bash 1206 | git config --global format.pretty "%Cgreen%h%Creset %s %Cblue@%cn%Creset %Cred%ai%Creset" # 全局配置彩色 log 输出 1207 | git config --global format.pretty "%h: %s @%cn %ai" # 全局配置格式化后的 log 1208 | git config format.pretty oneline # 显示历史记录时,每个提交的信息只显示一行 1209 | git config color.ui true # 彩色的 git 输出 1210 | git log # 查看最近的提交日志 1211 | git log --grep=224 # 这条命令是查看含有 "224" 关键字的 git commit 1212 | git log --pretty=oneline # 单行显示提交日志 1213 | git log --graph --pretty=oneline --abbrev-commit 1214 | git log -num # 显示第几条log(倒数) 1215 | git reflog # 查看所有分支的所有操作记录 1216 | git log --since=1.day # 一天内的提交;你可以给出各种时间格式,比如说具体的某一天(“2008-01-15”),或者是多久以前(“2 years 1 day 3 minutes ago”)。 1217 | git log --pretty="%h - %s" --author=自己的名字 # 查看自己的日志 1218 | git log -p -2 # 展开两次更新显示每次提交的内容差异 1219 | git log --stat # 要快速浏览其他协作者提交的更新都作了哪些改动 1220 | git log --pretty=format:"%h - %an, %ar : %s"# 定制要显示的记录格式 1221 | git log --pretty=format:'%h : %s' --date-order --graph # 拓扑顺序展示 1222 | git log --pretty=format:'%h : %s - %ad' --date=short # 日期YYYY-MM-DD显示 1223 | git log --pretty=oneline --graph --decorate --all # 展示简化的 commit 历史 1224 | git log HEAD --pretty=format:%s # 只显示commit 1225 | git config --global format.pretty '%h : %s - %ad' --date=short #日期YYYY-MM-DD显示 写入全局配置 1226 | ``` 1227 | 1228 | |选项 | 说明|选项 | 说明| 1229 | |----|----|----|----| 1230 | |%H |提交对象(commit)的完整哈希字串 |%ad |作者修订日期(可以用 -date= 选项定制格式)| 1231 | |%h |提交对象的简短哈希字串 |%ar |作者修订日期,按多久以前的方式显示| 1232 | |%T |树对象(tree)的完整哈希字串 |%cn |提交者(committer)的名字| 1233 | |%t |树对象的简短哈希字串 |%ce |提交者的电子邮件地址| 1234 | |%P |父对象(parent)的完整哈希字串 |%cd |提交日期| 1235 | |%p |父对象的简短哈希字串 |%cr |提交日期,按多久以前的方式显示| 1236 | |%an |作者(author)的名字 |%s |提交说明| 1237 | |%ae |作者的电子邮件地址| - | - | 1238 | 1239 | [Pretty Formats](https://git-scm.com/docs/git-log#_pretty_formats) 1240 | 1241 | ## 重写历史 1242 | 1243 | ```bash 1244 | git commit --amend # 改变最近一次提交 1245 | git rebase -i HEAD~3 # 修改最近三次的提交说明,或者其中任意一次 1246 | git commit --amend # 保存好了,这些指示很明确地告诉了你该干什么 1247 | git rebase --continue # 修改提交说明,退出编辑器。 1248 | ``` 1249 | 1250 | ```bash 1251 | pick f7f3f6d changed my name a bit 1252 | pick 310154e updated README formatting and added blame 1253 | pick a5f4a0d added cat-file 1254 | ``` 1255 | 1256 | 改成 1257 | 1258 | ``` 1259 | pick 310154e updated README formatting and added blame 1260 | pick f7f3f6d changed my name a bit 1261 | ``` 1262 | 1263 | ## 其它 1264 | 1265 | ```bash 1266 | git help * # 获取命令的帮助信息 1267 | git status # 获取当前的状态,非常有用,因为git会提示接下来的能做的操作 1268 | ``` 1269 | 1270 | 1271 | ## 报错问题解决 1272 | 1273 | **1. `git fatal: protocol error: bad line length character: No s`** 1274 | 1275 | 解决办法:更换remote地址为 `http/https` 的 1276 | 1277 | **2. `The requested URL returned error: 403 Forbidden while accessing`** 1278 | 1279 | 解决github push错误的办法: 1280 | 1281 | ```shell 1282 | #vim 编辑器打开 当前项目中的config文件 1283 | vim .git/config 1284 | 1285 | #修改 1286 | [remote "origin"] 1287 | url = https://github.com/jaywcjlove/example.git 1288 | 1289 | #为下面代码 1290 | [remote "origin"] 1291 | url = https://jaywcjlove@github.com/jaywcjlove/example.git 1292 | ``` 1293 | 1294 | **3. git status 显示中文问题** 1295 | 1296 | 在查看状态的时候 git status 如果是中文就显示下面的情况 1297 | 1298 | ```bash 1299 | \344\272\247\345\223\201\351\234\200\346\261\202 1300 | ``` 1301 | 1302 | 解决这个问题方法是: 1303 | 1304 | ```bash 1305 | git config --global core.quotepath false 1306 | ``` 1307 | 1308 | **4. The authenticity of host 192.168.0.xxx can't be establis** 1309 | 1310 | 修改 `/etc/ssh/ssh_config` 中的 `StrictHostKeyChecking` 的 `ask` 为 `no` 解决问题。 1311 | 1312 | **5. SSH连接时出现 Host key verification failed 的原因及解决方法** 1313 | 1314 | 用 OpenSSH 的人都知 ssh 会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时,OpenSSH 会核对公钥。如果公钥不同,OpenSSH 会发出警告,避免你受到 DNS Hijack 之类的攻击。 1315 | SSH 对主机的 public_key 的检查等级是根据 1316 | 1317 | ```bash 1318 | StrictHostKeyChecking=no # 最不安全的级别,当然也没有那么多烦人的提示了,相对安全的内网测试时建议使用。如果连接server的key在本地不存在,那么就自动添加到文件中(默认是known_hosts),并且给出一个警告。 1319 | StrictHostKeyChecking=ask # 默认的级别,就是出现刚才的提示了。如果连接和key不匹配,给出提示,并拒绝登录。 1320 | StrictHostKeyChecking=yes # 最安全的级别,如果连接与key不匹配,就拒绝连接,不会提示详细信息。 1321 | ``` 1322 | 1323 | 【解决方法1】在 `.ssh/config`(或者`/etc/ssh/ssh_config`)中配置: 1324 | 1325 | ```conf 1326 | StrictHostKeyChecking no 1327 | UserKnownHostsFile /dev/null 1328 | ``` 1329 | 1330 | 解决方法 2 1331 | 1332 | ```bash 1333 | vi ~/.ssh/known_hosts # 删除对应ip的相关rsa信息 1334 | rm known_hosts # 或者直接全部删除 1335 | ``` 1336 | 1337 | **5. insufficient permission for adding an object to repository database .git/objects** 1338 | 1339 | ``` 1340 | cd .git/objects 1341 | ls -al 1342 | sudo chown -R yourname:yourgroup * 1343 | ``` 1344 | 1345 | ## 参考资料 1346 | 1347 | - [Git官网](http://git-scm.com/) 1348 | - [**Github 15分钟学习Git**](https://try.github.io) 1349 | - [Git参考手册](http://gitref.org/zh/index.html) 1350 | - [Git简明手册](http://www.mceiba.com/tool/git-cheat-sheet.html) 1351 | - [Git Magic](http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/) 1352 | - [Git Community Book 中文版](http://gitbook.liuhui998.com/index.html) 1353 | - [Pro Git](http://git-scm.com/book/en/v2) 1354 | - [图解Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html) 1355 | - [git-简明指南](http://rogerdudler.github.io/git-guide/index.zh.html) 1356 | - [learnGitBranching 在线学习工具](http://pcottle.github.io/learnGitBranching/) 1357 | - [初级教程](http://rogerdudler.github.io/git-guide/index.zh.html) 1358 | - [廖雪峰的Git教程](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) 1359 | - [蒋鑫老师将带你入github的大门](http://www.worldhello.net/gotgithub/) 1360 | - [git详解](http://www.open-open.com/lib/view/open1328069609436.html) 1361 | - [oschina教程](http://git.oschina.net/progit/) 1362 | - [How to undo (almost) anything with Git撤销一切,汇总各种回滚撤销的场景,加强学习。](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) 1363 | - [Git 教程 | 菜鸟教程runoob.com](http://www.runoob.com/git/git-tutorial.html) 1364 | - [Git 本地仓库和裸仓库](https://gold.xitu.io/post/5842f9b861ff4b005889ade6) 1365 | - [沉浸式学 Git](http://www.kancloud.cn/kancloud/igit/46710) 1366 | - [Git进阶用法,主要是rebase高级用法](http://way.oschina.io/2016/12/15/notes/GitAdvance/?utm_source=gank.io&utm_medium=email) 1367 | - [成为一个git大师](https://www.atlassian.com/git/tutorials) 1368 | - [高质量的Git中文教程](https://github.com/geeeeeeeeek/git-recipes) 1369 | 1370 | ## Contributors 1371 | 1372 | As always, thanks to our amazing contributors! 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | Made with [action-contributors](https://github.com/jaywcjlove/github-action-contributors). 1379 | 1380 | ## License 1381 | 1382 | MIT © [Kenny Wong](https://github.com/jaywcjlove) 1383 | -------------------------------------------------------------------------------- /cheatsheet.md: -------------------------------------------------------------------------------- 1 | 2 | 入门备忘清单 3 | === 4 | 5 | 6 | ![Git 入门备忘清单](./git.png) 7 | 8 | 9 | ## 创建存储库 10 | 11 | ```bash 12 | # 创建一个新的本地存储库 13 | $ git init [项目名称] 14 | 15 | # 克隆存储库 16 | $ git clone 17 | 18 | # 将存储库克隆到指定目录 19 | $ git clone <我的文件夹> 20 | ``` 21 | 22 | ## 配置 23 | 24 | ```bash 25 | # 设置将附加到您的提交(commit)和标签(tags)的名称 26 | $ git config --global user.name "name" 27 | 28 | # 设置将附加到您的提交(commit)和标签(tags)的电子邮件地址 29 | $ git config --global user.email "email" 30 | 31 | # 启用 Git 输出的一些着色 32 | $ git config --global color.ui auto 33 | 34 | # 在文本编辑器中编辑全局配置文件 35 | $ git config --global --edit 36 | ``` 37 | 38 | ## 变更 39 | 40 | ```bash 41 | # 在工作目录中显示修改后的文件,为您的下一次提交暂存 42 | $ git status 43 | 44 | # 暂存文件,准备提交 45 | $ git add [file] 46 | 47 | # 暂存所有更改的文件,准备提交 48 | $ git add . 49 | 50 | # 将所有暂存文件提交到版本化历史记录 51 | $ git commit -m "commit message" 52 | 53 | # 将所有跟踪的文件提交到版本化历史记录 54 | $ git commit -am "commit message" 55 | 56 | # 取消暂存文件,保留文件更改 57 | $ git reset [file] 58 | 59 | # 将所有内容恢复到最后一次提交 60 | $ git reset --hard 61 | 62 | # 已更改但未暂存(staged)的内容的差异 63 | $ git diff 64 | 65 | # 已暂存(staged)但尚未提交的内容的差异 66 | $ git diff --staged 67 | 68 | # 在指定之前应用当前分支的任何提交 69 | $ git rebase [branch] 70 | ``` 71 | 72 | ## 分支 73 | 74 | ```bash 75 | # 列出所有本地分支 76 | $ git branch 77 | 78 | # 列出所有分支,本地和远程 79 | $ git branch -av 80 | 81 | # 切换到 my_branch,并更新工作目录 82 | $ git checkout my_branch 83 | 84 | # 创建一个名为 new_branch 的新分支 85 | $ git checkout -b new_branch 86 | 87 | # 删除名为 my_branch 的分支 88 | $ git branch -d my_branch 89 | 90 | # 将 branchA 分支合并到 branchB 分之上 91 | $ git checkout branchB 92 | $ git merge branchA 93 | 94 | # 标记当前提交 95 | $ git tag my_tag 96 | 97 | # 重命名为 new_name 98 | $ git branch -m 99 | 100 | # 推送和重置 101 | $ git push origin -u 102 | 103 | # 删除远程分支 104 | $ git push origin --delete 105 | ``` 106 | 107 | ## 观察存储库 108 | 109 | ```bash 110 | # 显示当前活动分支的提交历史 111 | $ git log 112 | 113 | # 显示 branchA 上不在 branchB 上的提交 114 | $ git log branchB..branchA 115 | 116 | # 显示更改文件的提交,即使重命名 117 | $ git log --follow [file] 118 | 119 | # 显示 branchA 中的内容与 branchB 中的差异 120 | $ git diff branchB...branchA 121 | 122 | # 在 Git 中以 人类可读 格式显示任何对象 123 | $ git show [SHA] 124 | 125 | # 按内容搜索更改 126 | $ git log -S'' 127 | 128 | # 显示特定文件随时间的变化 129 | $ git log -p 130 | 131 | # 打印出很酷的日志可视化 132 | $ git log --pretty=oneline --graph --decorate --all 133 | ``` 134 | 135 | ## 同步 136 | 137 | ```bash 138 | # 从该 Git 远程获取所有分支 139 | $ git fetch [alias] 140 | 141 | # 将远程分支合并到当前分支以使其保持最新状态 142 | $ git merge [alias]/[branch] 143 | No fast-forward 144 | $ git merge --no-ff [alias]/[branch] 145 | Only fast-forward 146 | $ git merge --ff-only [alias]/[branch] 147 | 148 | # 将本地分支提交传输到远程存储库分支 149 | $ git push [alias] [branch] 150 | 151 | # 从跟踪远程分支获取并合并任何提交 152 | $ git pull 153 | 154 | # 将另一个分支的一个特定提交合并到当前分支 155 | $ git cherry-pick [commit_id] 156 | ``` 157 | 158 | ## 远程 159 | 160 | ```bash 161 | # 添加一个 git URL 作为别名(alias) 162 | $ git remote add [alias] [url] 163 | 164 | # 显示您设置的远程存储库的名称 165 | $ git remote 166 | 167 | # 显示远程存储库的名称和 URL 168 | $ git remote -v 169 | 170 | # 删除远程存储库 171 | $ git remote rm [remote repo name] 172 | 173 | # 更改 git repo 的 URL 174 | $ git remote set-url origin [git_url] 175 | ``` 176 | 177 | ## 临时提交 178 | 179 | ```bash 180 | # 保存已修改和分阶段的更改 181 | $ git stash 182 | 183 | # 列出隐藏文件更改的堆栈顺序 184 | $ git stash list 185 | 186 | # 从存储堆栈顶部编写工作 187 | $ git stash pop 188 | 189 | # 丢弃存储堆栈顶部的更改 190 | $ git stash drop 191 | ``` 192 | 193 | ## 跟踪路径更改 194 | 195 | ```bash 196 | # 从项目中删除文件并暂存删除以进行提交 197 | $ git rm [file] 198 | 199 | # 更改现有文件路径并暂存移动 200 | $ git mv [existing-path] [new-path] 201 | 202 | # 显示所有提交日志,并指示任何移动的路径 203 | $ git log --stat -M 204 | ``` 205 | 206 | ## 忽略文件 207 | 208 | `.gitignore` 文件指定了 Git 应该忽略的故意未跟踪的文件 209 | 210 | ```bash 211 | /logs/* 212 | 213 | # "!" 意思是不要忽视 214 | !logs/.gitkeep 215 | 216 | # 忽略 Mac 系统文件 217 | .DS_store 218 | 219 | # 忽略 node_modules 文件夹 220 | node_modules 221 | 222 | # 忽略 SASS 配置文件 223 | .sass-cache 224 | ``` 225 | 226 | ## 分支 227 | 228 | ```bash 229 | # 列出所有分支及其上游 230 | $ git branch -vv 231 | 232 | # 快速切换到上一个分支 233 | $ git checkout - 234 | 235 | # 只获取远程分支 236 | $ git branch -r 237 | 238 | # 从另一个分支签出单个文件 239 | $ git checkout -- 240 | ``` -------------------------------------------------------------------------------- /git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jaywcjlove/git-tips/3163657a0e457d2a47081d09cadc91a0538c74d4/git.png -------------------------------------------------------------------------------- /git.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /idoc.yml: -------------------------------------------------------------------------------- 1 | site: Git Tips 2 | title: Git 的一些使用技巧和笔记 3 | keywords: git,tips,handbook 4 | logo: ./git.svg 5 | favicon: ./git.svg 6 | editButton: 7 | label: Edit this page on GitHub 8 | url: https://github.com/jaywcjlove/git-tips/blob/master/ 9 | 10 | footer: | 11 | Released under the MIT License. Copyright © 2022 Kenny Wong
12 | Generated by
idoc 13 | 14 | sideEffectFiles: 15 | - cheatsheet.md 16 | 17 | menus: 18 | 首页: index.html 19 | 入门清单: cheatsheet.html 20 | Sponsor: https://jaywcjlove.github.io/#/sponsor -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "git-tips", 3 | "version": "1.0.0", 4 | "scripts": { 5 | "start": "idoc --watch", 6 | "build": "idoc" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/jaywcjlove/git-tips.git" 11 | }, 12 | "dependencies": { 13 | "idoc": "^1.25.0" 14 | } 15 | } --------------------------------------------------------------------------------