{"id":15626924,"url":"https://github.com/jaywcjlove/git-tips","last_synced_at":"2025-04-04T23:09:28.515Z","repository":{"id":40313570,"uuid":"181043517","full_name":"jaywcjlove/git-tips","owner":"jaywcjlove","description":"这里是我的笔记，记录一些git常用和一些记不住的命令。","archived":false,"fork":false,"pushed_at":"2024-06-23T06:43:57.000Z","size":266,"stargazers_count":427,"open_issues_count":0,"forks_count":132,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-29T10:38:55.374Z","etag":null,"topics":["git","gitbook","github","tips"],"latest_commit_sha":null,"homepage":"https://jaywcjlove.github.io/git-tips","language":"Markdown","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jaywcjlove.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"ko_fi":"jaywcjlove","buy_me_a_coffee":"jaywcjlove","custom":["https://www.paypal.me/kennyiseeyou","https://jaywcjlove.github.io/#/sponsor"]}},"created_at":"2019-04-12T16:18:28.000Z","updated_at":"2024-10-28T00:47:38.000Z","dependencies_parsed_at":"2024-11-11T17:32:14.730Z","dependency_job_id":"83346b0c-6960-409d-8102-79f5ac1fa23c","html_url":"https://github.com/jaywcjlove/git-tips","commit_stats":{"total_commits":46,"total_committers":2,"mean_commits":23.0,"dds":0.08695652173913049,"last_synced_commit":"3163657a0e457d2a47081d09cadc91a0538c74d4"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaywcjlove%2Fgit-tips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaywcjlove%2Fgit-tips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaywcjlove%2Fgit-tips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaywcjlove%2Fgit-tips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaywcjlove","download_url":"https://codeload.github.com/jaywcjlove/git-tips/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247261612,"owners_count":20910108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","gitbook","github","tips"],"created_at":"2024-10-03T10:14:27.676Z","updated_at":"2025-04-04T23:09:28.492Z","avatar_url":"https://github.com/jaywcjlove.png","language":"Markdown","readme":"\u003c!--idoc:ignore:start--\u003e\nGit Tips\n===\n\u003c!--idoc:ignore:end--\u003e\n\n[![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor)\n[![Gitee Tips](https://jaywcjlove.github.io/sb/ico/gitee.svg)](https://jaywcjlove.gitee.io/git-tips/)\n[![CI](https://github.com/jaywcjlove/git-tips/actions/workflows/ci.yml/badge.svg)](https://github.com/jaywcjlove/git-tips/actions/workflows/ci.yml)\n\n一些使用技巧和笔记笔记，记录一些 git 常用和一些记不住的命令，这个笔记原本是基于 [颜海镜的文章](http://yanhaijing.com/git/2014/11/01/my-git-note)增加的，后面慢慢增加了许多内容，独立一个仓库维护，方便查询和使用。\n\n\u003c!--idoc:ignore:start--\u003e\n目录\n===\n\n\u003c!-- TOC --\u003e\n\n- [入门备忘清单](./cheatsheet.md)\n- [安装卸载](#安装卸载)\n- [配置管理](#配置管理)\n- [不常见的使用场景](#不常见的使用场景)\n  - [忽略文件的权限变化](#忽略文件的权限变化)\n  - [设置大小写敏感](#设置大小写敏感)\n  - [配置自动换行](#配置自动换行)\n  - [创建SSH密钥](#创建ssh密钥)\n  - [多账号ssh配置](#多账号ssh配置)\n  - [免密码登录远程服务器](#免密码登录远程服务器)\n  - [https协议下提交代码免密码](#https协议下提交代码免密码)\n  - [文件推向3个git库](#文件推向3个git库)\n  - [修改远程仓库地址](#修改远程仓库地址)\n  - [撤销远程记录](#撤销远程记录)\n  - [放弃本地的文件修改](#放弃本地的文件修改)\n  - [最简单放弃本地修改内容](#最简单放弃本地修改内容)\n  - [回退到某一个版本](#回退到某一个版本)\n  - [搜索 commit 历史记录](#搜索-commit-历史记录)\n  - [回滚到某个commit提交](#回滚到某个commit提交)\n  - [去掉某个commit](#去掉某个commit)\n  - [把 A 分支的某一个 commit，放到 B 分支上](#把-a-分支的某一个-commit放到-b-分支上)\n  - [获取最近一次提交的 commit id](#获取最近一次提交的-commit-id)\n  - [两个 git 仓库合并](#两个-git-仓库合并)\n  - [合并多个commit](#合并多个commit)\n  - [修改远程Commit记录](#修改远程commit记录)\n  - [利用commit关闭一个issue](#利用commit关闭一个issue)\n  - [新建一个空分支](#新建一个空分支)\n  - [添加忽略文件](#添加忽略文件)\n  - [忽略某个文件的改动](#忽略某个文件的改动)\n  - [同步fork的上游仓库](#同步fork的上游仓库)\n  - [手动合并冲突的 Pull Request](#手动合并冲突的-pull-request)\n  - [修改作者名](#修改作者名)\n  - [批量修改历史commit中的名字和邮箱](#批量修改历史commit中的名字和邮箱)\n  - [查看两个星期内的改动](#查看两个星期内的改动)\n  - [查看某个文件历史](#查看某个文件历史)\n  - [查看git仓库中最近修改的分支](#查看git仓库中最近修改的分支)\n  - [更新所有本地分支](#更新所有本地分支)\n  - [打造自己的git命令](#打造自己的git命令)\n  - [删除已经合并到 master 的分支](#删除已经合并到-master-的分支)\n  - [中文乱码的解决方案](#中文乱码的解决方案)\n  - [提交一个空文件夹](#提交一个空文件夹)\n- [新建仓库](#新建仓库)\n  - [init](#init)\n  - [status](#status)\n  - [add](#add)\n  - [commit](#commit)\n  - [remote](#remote)\n  - [push](#push)\n- [clone](#clone)\n- [本地](#本地)\n  - [help](#help)\n  - [add](#add-1)\n  - [rm](#rm)\n  - [commit](#commit-1)\n  - [reset](#reset)\n  - [revert](#revert)\n  - [checkout](#checkout)\n  - [diff](#diff)\n  - [stash](#stash)\n  - [merge](#merge)\n  - [cherry-pick](#cherry-pick)\n  - [rebase](#rebase)\n- [分支branch](#分支branch)\n  - [删除](#删除)\n  - [提交](#提交)\n  - [拉取](#拉取)\n  - [分支合并](#分支合并)\n  - [重命名](#重命名)\n  - [查看](#查看)\n  - [新建](#新建)\n  - [连接](#连接)\n  - [分支切换](#分支切换)\n- [远端](#远端)\n- [submodule](#submodule)\n  - [更新 submodule](#更新-submodule)\n  - [删除 submodule](#删除-submodule)\n  - [转换分支](#转换分支)\n- [删除文件](#删除文件)\n- [remote](#remote-1)\n- [标签tag](#标签tag)\n  - [重命名Tag](#重命名tag)\n- [日志log](#日志log)\n- [重写历史](#重写历史)\n- [其它](#其它)\n- [报错问题解决](#报错问题解决)\n- [参考资料](#参考资料)\n\n\u003c!-- /TOC --\u003e\n\u003c!--idoc:ignore:end--\u003e\n\n## 安装卸载\n\n[官方教程](https://git-scm.com/download/linux)，在 Linux/Unix 系统中，通过工具在中安装 `git`,这种方式比较简单，便于升级卸载工具。\n\n下面介绍在 CentOS 系统中，通过 yum 来安装 git\n\n\u003e **Red Hat Enterprise Linux, Oracle Linux, CentOS, Scientific Linux, et al.**\n\u003e 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.\n\n官方文档说 git 在 `RHEL` 和衍生产品通常都会发布旧版本的 `git`，我们需要源码编译安装，或者使用第三方存储库（如[IUS社区项目](https://ius.io/)）。\n\n现在我们通过，[IUS社区](https://ius.io/GettingStarted/)下载 [ius-release.rpm](https://centos7.iuscommunity.org/ius-release.rpm) 文件进行安装\n\n```bash\n# 注意下载不同的版本，本机 CentOS 7\nwget https://centos7.iuscommunity.org/ius-release.rpm\n# 安装rpm文件\nrpm -ivh ius-release.rpm\n```\n\n查看可安装的git安装包\n\n```bash\nrepoquery --whatprovides git\n# git-0:1.8.3.1-13.el7.x86_64\n# git2u-0:2.16.5-1.ius.centos7.x86_64\n# git2u-0:2.16.2-1.ius.centos7.x86_64\n# git2u-0:2.16.4-1.ius.centos7.x86_64\n# git-0:1.8.3.1-14.el7_5.x86_64\n```\n\n**yum 卸载 git 安装新版本**\n\n卸载 `1.8.3` 的 `git`，安装 `2.16.5` 的 `git`\n\n```bash\n# 卸载老的版本\nyum remove git\n# 安装新的版本\nyum install git2u\n```\n\n## 配置管理\n\n首先是配置帐号信息 `ssh -T git@github.com` 测试。\n\n```bash\ngit help config    # 获取帮助信息，查看修改个人信息的参数  \ngit config --list  # 查看配置的信息\ngit config --global user.name \"小弟调调\"          # 修改全局名字\ngit config --global user.email \"wowohoo@qq.com\"  # 修改全局邮箱\ngit config --global --unset \u003centry-name\u003e  # 删除全局设置\n```\n\n## 不常见的使用场景\n\n### 忽略文件的权限变化\n\n不再将文件的权限变化视作改动\n\n```bash\ngit config core.fileMode false\n```\n\n### 设置大小写敏感\n\n```bash\ngit config --get core.ignorecase # 查看git 的设置\ngit config core.ignorecase false # 设置大小写敏感\ngit rm -r --cached \u003c目录/文件\u003e  # 远程有俩相同目录，通过这种方式清除掉，然后提交记录\n```\n\n### 配置自动换行\n\n自动转换坑太大，提交到git是自动将换行符转换为lf \n\n```bash\ngit config --global core.autocrlf input\n```\n\n### 创建SSH密钥\n\n这个密钥用来跟 github 通信，在本地终端里生成然后上传到 github\n\n```bash\nssh-keygen -t rsa -C 'wowohoo@qq.com' # 生成密钥  \nssh-keygen -t rsa -C \"wowohoo@qq.com\" -f ~/.ssh/ww_rsa # 指定生成目录文件名字\nssh -T git@github.com # 测试是否成功  \n```\n\n### 多账号ssh配置\n\n**1.生成指定名字的密钥**\n\n`ssh-keygen -t rsa -C \"邮箱地址\" -f ~/.ssh/jslite_rsa`  \n会生成 `jslite_rsa` 和 `jslite_rsa.pub` 这两个文件  \n\n**2.密钥复制到托管平台上**\n\n`vim ~/.ssh/jslite_rsa.pub`   \n打开公钥文件 `jslite_rsa.pub` ，并把内容复制至代码托管平台上   \n\n**3.修改config文件**\n\n`vim ~/.ssh/config` #修改config文件，如果没有创建 `config`  \n\n```shell\nHost jslite.github.com\n  HostName github.com\n  User git\n  IdentityFile ~/.ssh/jslite_rsa\n\nHost work.github.com\n  HostName github.com\n  # Port 服务器open-ssh端口（默认：22,默认时一般不写此行）\n  # PreferredAuthentications 配置登录时用什么权限认证 \n  #                          publickey|password publickey|keyboard-interactive等\n  User git\n  IdentityFile ~/.ssh/work_rsa\n```\n\n- `Host` 这里是个别名可以随便命名\n- `HostName` 一般是网站如：`git@ss.github.com:username/repo.git` 填写 `github.com`\n- `User` 通常填写`git`\n- `IdentityFile` 使用的公钥文件地址\n\n**4.测试**\n\n```bash\nssh -T git@jslite.github.com  # `@`后面跟上定义的Host  \nssh -T work.github.com        # 通过别名测试\nssh -i ~/公钥文件地址 Host别名  # 如 ssh -i ~/.ssh/work_rsa work.github.com\n```\n\n**5.使用**\n\n```bash\n# 原来的写法\ngit clone git@github.com:\u003cjslite的用户名\u003e/learngit.git\n# 现在的写法\ngit clone git@jslite.github.com:\u003cjslite的用户名\u003e/learngit.git\ngit clone git@work.github.com:\u003cwork的用户名\u003e/learngit.git\n```\n\n**5.注意**\n\n如果你修改了id_rsa的名字，你需要将ssh key添加到SSH agent中，如：\n\n```bash\nssh-add ~/.ssh/jslite_rsa\nssh-add -l  # 查看所有的key\nssh-add -D  # 删除所有的key\nssh-add -d  ~/.ssh/jslite_rsa # 删除指定的key\n```\n\n### 免密码登录远程服务器\n\n```bash\n$ ssh-keygen -t rsa -P '' -f ~/.ssh/aliyunserver.key\n$ ssh-copy-id -i ~/.ssh/aliyunserver.key.pub root@192.168.182.112 # 这里需要输入密码一次\n```\n\n编辑 `~/.ssh/config`\n\n```bash\nHost aliyun1\n  HostName 192.168.182.112\n  User root\n  PreferredAuthentications publickey\n  IdentityFile ~/.ssh/aliyunserver.key\n```\n\n上面配置完了，可以通过命令登录，不需要输入IP地址和密码 `ssh aliyun1`\n\n### https协议下提交代码免密码\n\n```bash\ngit clone https://github.com/username/rep.git\n```\n\n通过上面方式克隆可能需要密码，解决办法：进入当前克隆的项目 `vi rep/.git/config` 编辑 `config`, 按照下面方式修改，你就可以提交代码不用输入密码了。\n\n```diff\n[core]\n\trepositoryformatversion = 0\n\tfilemode = true\n\tbare = false\n\tlogallrefupdates = true\n\tignorecase = true\n\tprecomposeunicode = true\n[remote \"origin\"]\n-\turl = https://github.com/username/rep.git\n+\turl = https://用户名:密码@github.com/username/rep.git\n\tfetch = +refs/heads/*:refs/remotes/origin/*\n[branch \"master\"]\n\tremote = origin\n\tmerge = refs/heads/master\n```\n\n### 文件推向3个git库\n\n**1. 增加3个远程库地址**\n\n```shell\ngit remote add origin https://github.com/JSLite/JSLite.git  \ngit remote set-url --add origin https://gitlab.com/wang/JSLite.js.git  \ngit remote set-url --add origin https://oschina.net/wang/JSLite.js.git  \n```\n\n**2. 删除其中一个 set-url 地址**\n\n```shell\nusage: git remote set-url [--push] \u003cname\u003e \u003cnewurl\u003e [\u003coldurl\u003e]\n   or: git remote set-url --add \u003cname\u003e \u003cnewurl\u003e\n   or: git remote set-url --delete \u003cname\u003e \u003curl\u003e\n```\n\n`git remote set-url --delete origin https://oschina.net/wang/JSLite.js.git`\n\n**3.推送代码**\n\n```bash\ngit push origin master\ngit push -f origin master  # 强制推送  \n```\n\n**4.拉代码**\n\n只能拉取 `origin` 里的一个url地址，这个fetch-url  \n默认为你添加的到 `origin`的第一个地址  \n\n```shell\ngit pull origin master   \ngit pull --all # 获取远程所有内容包括tag  \ngit pull origin next:master # 取回origin主机的next分支，与本地的master分支合并  \ngit pull origin next # 远程分支是与当前分支合并  \n\n# 上面一条命令等同于下面两条命令   \ngit fetch origin  \ngit merge origin/next  \n```\n\n如果远程主机删除了某个分支，默认情况下，git pull 不会在拉取远程分支的时候，删除对应的本地分支。这是为了防止，由于其他人操作了远程主机，导致git pull不知不觉删除了本地分支。  \n但是，你可以改变这个行为，加上参数 -p 就会在本地删除远程已经删除的分支。  \n\n```shell\n$ git pull -p\n# 等同于下面的命令\n$ git fetch --prune origin \n$ git fetch -p\n```\n\n**5.更改pull**\n\n只需要更改config文件里，那三个url的顺序即可，fetch-url会直接对应排行第一的那个utl连接。    \n\n\n### 修改远程仓库地址\n\n```bash\ngit remote remove origin  # 删除该远程路径  \ngit remote add origin git@jslite.github.com:JSLite/JSLite.git  # 添加远程路径 \n```\n\n### 撤销远程记录\n\n```shell\ngit reset --hard HEAD~1 # 撤销一条记录   \ngit push -f origin HEAD:master # 同步到远程仓库  \n```\n\n### 放弃本地的文件修改\n\n```shell\ngit reset --hard FETCH_HEAD # FETCH_HEAD表示上一次成功git pull之后形成的commit点。然后git pull\n```\n\n`git reset --hard FETCH_HEAD` 出现错误\n\n```bash\ngit pull\nYou are not currently on a branch, so I cannot use any\n'branch.\u003cbranchname\u003e.merge' in your configuration file.\nPlease specify which remote branch you want to use on the command\nline and try again (e.g. 'git pull \u003crepository\u003e \u003crefspec\u003e').\nSee git-pull(1) FOR details.\n```\n\n解决方法：\n\n```bash\ngit checkout -b temp # 新建+切换到temp分支 \ngit checkout master\n```\n\n### 最简单放弃本地修改内容\n\n```bash\n# 如果有的修改以及加入暂存区的话\ngit reset --hard \n# 还原所有修改，不会删除新增的文件\ngit checkout . \n# 下面命令会删除新增的文件\ngit clean -xdf\n```\n\n通过存储暂存区stash，在删除暂存区的方法放弃本地修改。\n\n```bash\ngit stash \u0026\u0026 git stash drop \n```\n\n### 回退到某一个版本\n\n```bash\ngit reset --hard \u003chash\u003e\n# 例如 git reset --hard a3hd73r\n# --hard代表丢弃工作区的修改，让工作区与版本代码一模一样，与之对应，\n# --soft参数代表保留工作区的修改。\n```\n\n### 搜索 commit 历史记录\n\n```shell\ngit log --grep=224\n# 这条命令是查看含有 \"224\" 关键字的 git commit \n```\n\n### 回滚到某个commit提交\n\n```shell\ngit revert HEAD~1 # 撤销一条记录 会弹出 commit 编辑\ngit push # 提交回滚\n```\n\n### 去掉某个commit\n\n```bash\n# 实质是新建了一个与原来完全相反的commit，抵消了原来commit的效果\ngit revert \u003ccommit-hash\u003e \n```\n\n### 把 A 分支的某一个 commit，放到 B 分支上\n\n对两个分支，同时都拥有的文件，进行修改后，再同时 `commit` 到这两个分支，比如 `master` 分支和 `branch1` 分支，都拥有文件 `test.js` ，在 `master` 或者 `branch1` 分支下对 `test.js` 进行修改后，把修改的 `test.js` 同时提交到 `master` 分支和 `branch1` 分支。\n\n```bash\ngit checkout \u003cbranch-name\u003e \u0026\u0026 git cherry-pick \u003ccommit-id\u003e\n```\n\n### 获取最近一次提交的 commit id\n\n```bash\ngit rev-parse HEAD # e10721cb8859b2cd340d31a52ef4bf4b9629ddda\ngit rev-parse --short HEAD # e10721c\n```\n\n### 两个 git 仓库合并\n\n现在有两个仓库 [kktjs/kkt](https://github.com/kktjs/kkt.git) 和 [kktjs/kkt-next](https://github.com/kktjs/kkt-next.git) 我们需要将 `kkt-next` 仓库合并到 `kkt` 并保留 `kkt-next` 的所有提交内容。\n\n```bash\n# 1. 克隆主仓库代码\ngit clone git@github.com:kktjs/kkt.git\n# 2. 将 kkt-next 作为远程仓库，添加到 kkt 中，设置别名为 other\ngit remote add other git@github.com:kktjs/kkt-next.git\n# 3. 从 kkt-next 仓库中拉取数据到本仓库\ngit fetch other\n# 4. 将 kkt-next 仓库拉取的 master 分支作为新分支 checkout 到本地，新分支名设定为 kkt-next\ngit checkout -b kkt-next other/master\n# 5. 切换回 kkt 的 master 分支\ngit checkout master\n# 6. 将 kkt-next 合并入 kkt 的 master 分支\ngit merge kkt-next\n# 如果第 6 步报错 `fatal: refusing to merge unrelated histories`\n# 请执行下面命令 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\ngit merge kkt-next --allow-unrelated-histories\n```\n\n在合并时有可能两个分支对同一个文件都做了修改，这时需要解决冲突，对文本文件来说很简单，根据需要对冲突的位置进行处理就可以。对于二进制文件，需要用到如下命令:\n\n```bash\ngit checkout --theirs YOUR_BINARY_FILES     # 保留需要合并进来的分支的修改\ngit checkout --ours YOUR_BINARY_FILES       # 保留自己的修改\ngit add YOUR_BINARY_FILES\n```\n\n### 合并多个commit\n\n```bash\n# 这个命令，将最近4个commit合并为1个，HEAD代表当前版本。\n# 将进入VIM界面，你可以修改提交信息。\ngit rebase -i HEAD~4 \n# 可以看到其中分为两个部分，上方未注释的部分是填写要执行的指令，\n# 而下方注释的部分则是指令的提示说明。指令部分中由前方的命令名称、commit hash 和 commit message 组成\n# 当前我们只要知道 pick 和 squash 这两个命令即可。\n# --\u003e pick 的意思是要会执行这个 commit\n# --\u003e squash 的意思是这个 commit 会被合并到前一个commit\n\n# 我们将 需要保留的 这个 commit 前方的命令改成 squash 或 s，然后输入:wq以保存并退出\n# 这是我们会看到 commit message 的编辑界面\n\n# 其中, 非注释部分就是两次的 commit message, 你要做的就是将这两个修改成新的 commit message。\n# \n# 输入wq保存并推出, 再次输入git log查看 commit 历史信息，你会发现这两个 commit 已经合并了。\n# 将修改强制推送到前端\ngit push -f origin master\n```\n\n### 修改远程Commit记录\n\n```bash\ngit commit --amend\n# amend只能修改没有提交到线上的，最后一次commit记录\ngit rebase -i HEAD~3\n# 表示要修改当前版本的倒数第三次状态\n# 将要更改的记录行首单词 pick 改为 edit\npick 96dc3f9 doc: Update quick-start.md\npick f1cce8a test(Transition):Add transition test (#47)\npick 6293516 feat(Divider): Add Divider component.\n# Rebase eeb03a4..6293516 onto eeb03a4 (3 commands)\n#\n# Commands:\n# p, pick = use commit\n# r, reword = use commit, but edit the commit message\n# e, edit = use commit, but stop for amending\n# s, squash = use commit, but meld into previous commit\n# f, fixup = like \"squash\", but discard this commit's log message\n# x, exec = run command (the rest of the line) using shell\n# d, drop = remove commit\n```\n\n保存并退出，会弹出下面提示\n\n```bash\n# You can amend the commit now, with\n# \n#   git commit --amend\n# \n# Once you are satisfied with your changes, run\n# \n#   git rebase --continue\n\n# 通过这条命令进入编辑页面更改commit，保存退出\ngit commit --amend\n# 保存退出确认修改，继续执行 rebase, \ngit rebase --continue\n# 如果修改多条记录反复执行上面两条命令直到完成所有修改\n\n# 最后，确保别人没有提交进行push，最好不要加 -f 强制推送\ngit push -f origin master\n```\n\n### 利用commit关闭一个issue\n\n这个功能在Github上可以玩儿，Gitlab上特别老的版本不能玩儿哦，那么如何跟随着commit关闭一个issue呢? 在confirm merge的时候可以使用一下命令来关闭相关issue:  \n\n`fixes #xxx`、 `fixed #xxx`、 `fix #xxx`、 `closes #xxx`、 `close #xxx`、 `closed #xxx`、\n\n### 新建一个空分支\n\n```bash\n# 这种方式新建的分支(gh-pages)是没有 commit 记录的\ngit checkout --orphan gh-pages\n# 删除新建的gh-pages分支原本的内容，如果不删除，提交将作为当前分支的第一个commit\ngit rm -rf .\n# 查看一下状态 有可能上面一条命令，没有删除还没有提交的的文件\ngit state \n```\n\n### 添加忽略文件\n\n```\necho node_modules/ \u003e\u003e .gitignore\n```\n\n### 忽略某个文件的改动\n\n```bash\ngit update-index --assume-unchanged path/to/file # 关闭 track 指定文件的改动，也就是 Git 将不会在记录这个文件的改动\ngit update-index --no-assume-unchanged path/to/file # 恢复 track 指定文件的改动\n```\n\n### 同步fork的上游仓库\n\n[Github教程同步fork教程](https://help.github.com/articles/syncing-a-fork/)，[在Github上同步一个分支(fork)](http://www.miss77.net/549.html)  \n\n**设置添加多个远程仓库地址。**\n\n在同步之前，需要创建一个远程点指向上游仓库(repo).如果你已经派生了一个原始仓库，可以按照如下方法做。\n\n```shell \n$ git remote -v\n# List the current remotes （列出当前远程仓库）\n# origin  https://github.com/user/repo.git (fetch)\n# origin  https://github.com/user/repo.git (push)\n$ git remote add upstream https://github.com/otheruser/repo.git\n# Set a new remote (设置一个新的远程仓库)\n$ git remote -v\n# Verify new remote (验证新的原唱仓库)\n# origin    https://github.com/user/repo.git (fetch)\n# origin    https://github.com/user/repo.git (push)\n# upstream  https://github.com/otheruser/repo.git (fetch)\n# upstream  https://github.com/otheruser/repo.git (push)\n```\n\n**同步更新仓库内容**\n\n同步上游仓库到你的仓库需要执行两步：首先你需要从远程拉去，之后你需要合并你希望的分支到你的本地副本分支。从上游的存储库中提取分支以及各自的提交内容。 `master` 将被存储在本地分支机构 `upstream/master`\n\n```shell \ngit fetch upstream\n# remote: Counting objects: 75, done.\n# remote: Compressing objects: 100% (53/53), done.\n# remote: Total 62 (delta 27), reused 44 (delta 9)\n# Unpacking objects: 100% (62/62), done.\n# From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY\n#  * [new branch]      master     -\u003e upstream/master\n```\n\n检查你的 fork's 本地 `master` 分支\n\n```shell \ngit checkout master\n# Switched to branch 'master'\n```\n\n合并来自 `upstream/master` 的更改到本地 master  分支上。  这使你的前 fork's `master` 分支与上游资源库同步，而不会丢失你本地修改。  \n\n```shell \ngit merge upstream/master\n# Updating a422352..5fdff0f\n# Fast-forward\n#  README                    |    9 -------\n#  README.md                 |    7 ++++++\n#  2 files changed, 7 insertions(+), 9 deletions(-)\n#  delete mode 100644 README\n#  create mode 100644 README.md\n```\n\n### 手动合并冲突的 Pull Request\n\n以 [tsbbjs/tsbb](https://github.com/tsbbjs/tsbb) 为例，合并来自 [jaywcjlove/tsbb](https://github.com/jaywcjlove/tsbb) master分支的 `Pull Request`。\n\n```bash\n# 1. 克隆主仓库\ngit clone git@github.com:tsbbjs/tsbb.git \n# 2. 在主仓库 master 分支切个 jaywcjlove-master 分支出来，并且切换到 jaywcjlove-master 分支\ngit checkout -b jaywcjlove-master master\n# 3. 获取 jaywcjlove/tsbb 仓库 master 分支最新代码\ngit pull https://github.com/jaywcjlove/tsbb.git master\n# ⚠️ 注意下面是输出内容：\n# ----------------------\n# Auto-merging src/babel/transform.ts\n# CONFLICT (content): Merge conflict in src/babel/transform.ts\n# ----------------------\n# ⚠️ 注意上面 CONFLICT 标识是有冲突无法自动合并的代码，根据路径进入代码手动合并\n# 4. 合并完成之后，进行 commit 说明合并内容\ngit commit -m \"Merge branch 'master' of github.com:jaywcjlove/tsbb #3\"\n# 5. 切换到 master 分支，如果是 PR 其它分支，这里就切其它分支\ngit checkout master\n# 6. 合并 jaywcjlove-master 分支的代码\ngit merge --no-ff jaywcjlove-master\n# 7. 提交代码\ngit push origin master\n```\n\n### 修改作者名\n\n```\ngit commit --amend --author='Author Name \u003cemail@address.com\u003e'\n```\n\n### 批量修改历史commit中的名字和邮箱\n\n这是 [Github官方教程](https://help.github.com/articles/changing-author-info/)\n\n**1.克隆仓库**\n\n注意参数，这个不是普通的clone，clone下来的仓库并不能参与开发\n\n```bash\ngit clone --bare https://github.com/user/repo.git\ncd repo.git\n```\n\n**2.命令行中运行代码**\n\nOLD_EMAIL原来的邮箱  \nCORRECT_NAME更正的名字  \nCORRECT_EMAIL更正的邮箱  \n\n将下面代码复制放到命令行中执行\n\n```bash\ngit filter-branch -f --env-filter '\nOLD_EMAIL=\"wowohoo@qq.com\"\nCORRECT_NAME=\"小弟调调\"\nCORRECT_EMAIL=\"更正的邮箱@qq.com\"\nif [ \"$GIT_COMMITTER_EMAIL\" = \"$OLD_EMAIL\" ]\nthen\n    export GIT_COMMITTER_NAME=\"$CORRECT_NAME\"\n    export GIT_COMMITTER_EMAIL=\"$CORRECT_EMAIL\"\nfi\nif [ \"$GIT_AUTHOR_EMAIL\" = \"$OLD_EMAIL\" ]\nthen\n    export GIT_AUTHOR_NAME=\"$CORRECT_NAME\"\n    export GIT_AUTHOR_EMAIL=\"$CORRECT_EMAIL\"\nfi\n' --tag-name-filter cat -- --branches --tags\n```\n\n执行过程\n\n```bash\nRewrite 160d4df2689ff6df3820563bfd13b5f1fb9ba832 (479/508) (16 seconds passed, remaining 0 predicted)\nRef 'refs/heads/dev' was rewritten\nRef 'refs/heads/master' was rewritten\n```\n\n**3.同步到远程仓库**\n\n同步到push远程git仓库\n\n```bash\ngit push --force --tags origin 'refs/heads/*'\n```\n\n我还遇到了如下面错误，lab默认给master分支加了保护，不允许强制覆盖。`Project(项目)`-\u003e`Setting`-\u003e`Repository` 菜单下面的`Protected branches`把master的保护去掉就可以了。修改完之后，建议把master的保护再加回来，毕竟强推不是件好事。\n\n```bash\nremote: GitLab: You are not allowed to force push code to a protected branch on this project.\n```\n\n当上面的push 不上去的时候，先 `git pull` 确保最新代码\n\n```bash\ngit pull  --allow-unrelated-histories\n# 或者指定分枝\ngit pull origin master --allow-unrelated-histories\n```\n\n**4. 删除仓库**\n\n```bash\ncd ..\nrm -rf repo.git\n```\n\n### 查看两个星期内的改动\n\n```\ngit whatchanged --since='2 weeks ago'\n```\n\n### 查看某个文件历史\n\n```shell\ngit log --pretty=oneline 文件名  # 列出文件的所有改动历史  \ngit show c178bf49   # 某次的改动的修改记录  \ngit log -p c178bf49 # 某次的改动的修改记录  \ngit blame 文件名     # 显示文件的每一行是在那个版本最后修改。  \ngit whatchanged 文件名  # 显示某个文件的每个版本提交信息：提交日期，提交人员，版本号，提交备注（没有修改细节）  \n```\n\n### 查看git仓库中最近修改的分支\n\n```bash\ngit for-each-ref --count=30 --sort=-committerdate refs/heads/ --format='%(refname:short)'\n```\n\n### 更新所有本地分支\n\n```bash\ngit branch \\\n  --format \"%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)\" |\n  sh\n```\n\n### 打造自己的git命令\n\n```sh\ngit config --global alias.st status\ngit config --global alias.br branch\ngit config --global alias.co checkout\ngit config --global alias.ci commit\n```\n\n配置好后再输入git命令的时候就不用再输入一大段了，例如我们要查看状态，只需：\n\n```sh\ngit st\n```\n\n### 删除已经合并到 master 的分支\n\n```bash\ngit branch --merged master | grep -v '^\\*\\|  master' | xargs -n 1 git branch -d\n```\n\n### 中文乱码的解决方案\n\n```bash\ngit config --global core.quotepath false\n```\n\n### 提交一个空文件夹\n\n在空文件夹中建立一个文件 `.gitkeep`, 你就可以提交这个空文件夹了。\n\n## 新建仓库\n\n### init\n\n`git init` #初始化  \n\n### status\n\n`git status` #获取状态  \n\n### add\n\n`git add file` # .或*代表全部添加  \n`git rm --cached \u003cadded_file_to_undo\u003e` # 在commit之前撤销git add操作  \n`git reset head` # 好像比上面`git rm --cached`更方便  \n\n### commit\n\n`git commit -m \"message\"` #此处注意乱码  \n\n### remote\n\n`git remote add origin git@github.com:JSLite/test.git` #添加源  \n\n### push\n\n```bash\ngit push -u origin master # push同事设置默认跟踪分支  \ngit push origin master  \ngit push -f origin master # 强制推送文件，缩写 -f（全写--force）\n```\n\n## clone\n\n```bash\ngit clone git://github.com/JSLite/JSLite.js.git   \ngit clone git://github.com/JSLite/JSLite.js.git --depth=1  \ngit clone git://github.com/JSLite/JSLite.js.git mypro # 克隆到自定义文件夹  \ngit clone [user@]example.com:path/to/repo.git/ # SSH协议还有另一种写法。  \n```\n\ngit clone支持多种协议，除了HTTP(s)以外，还支持SSH、Git、本地文件协议等，下面是一些例子。`git clone \u003c版本库的网址\u003e \u003c本地目录名\u003e`  \n\n```shell\n$ git clone http[s]://example.com/path/to/repo.git/\n$ git clone ssh://example.com/path/to/repo.git/\n$ git clone ssh://example.com/path/to/repo.git/\n$ git clone git://example.com/path/to/repo.git/\n$ git clone /opt/git/project.git \n$ git clone file:///opt/git/project.git\n$ git clone ftp[s]://example.com/path/to/repo.git/\n$ git clone rsync://example.com/path/to/repo.git/\n```\n\n## 本地\n\n### help\n\n```bash\ngit help config # 获取帮助信息  \n```\n\n### add\n\n```shell\ngit add *   # 跟踪新文件   \ngit add -u [path]   # 添加[指定路径下]已跟踪文件   \n```\n\n### rm\n\n```shell\nrm *\u0026git rm *          # 移除文件  \ngit rm -f *            # 移除文件  \ngit rm --cached *      # 取消跟踪  \ngit mv file_from file_to  # 重命名跟踪文件  \ngit log   # 查看提交记录  \n```\n\n### commit\n\n```shell\ngit commit #提交更新   \ngit commit -m 'message' #提交说明   \ngit commit -a #跳过使用暂存区域，把所有已经跟踪过的文件暂存起来一并提交   \ngit commit --amend #修改最后一次提交   \ngit commit log #查看所有提交，包括没有push的commit    \ngit commit -m \"#133\" #关联issue 任意位置带上# 符号加上issue号码  \ngit commit -m \"fix #133\" commit关闭issue  \ngit commit -m '概要描述'$'\\n\\n''1.详细描述'$'\\n''2.详细描述' #提交简要描述和详细描述  \n```\n\n### reset\n\n```shell\ngit reset HEAD *  # 取消已经暂存的文件   \ngit reset --mixed HEAD * # 同上   \ngit reset --soft HEAD *  # 重置到指定状态，不会修改索引区和工作树   \ngit reset --hard HEAD *  # 重置到指定状态，会修改索引区和工作树   \ngit reset -- files *     # 重置index区文件   \n```\n\n### revert\n\n```shell\ngit revert HEAD   # 撤销前一次操作   \ngit revert HEAD~  # 撤销前前一次操作   \ngit revert commit # 撤销指定操作   \n```\n\n### checkout\n\n```shell\ngit checkout -- file  # 取消对文件的修改（从暂存区——覆盖worktree file）  \ngit checkout branch|tag|commit -- file_name  # 从仓库取出file覆盖当前分支   \ngit checkout HEAD~1 [文件]  # 将会更新 working directory 去匹配某次 commit   \ngit checkout -- .          # 从暂存区取出文件覆盖工作区   \ngit checkout -b gh-pages  0c304c9  # 这个表示 从当前分支 commit 哈希值为 0c304c9 的节点，分一个新的分支gh-pages出来，并切换到 gh-pages   \n```\n\n### diff\n\n```shell\ngit diff file     # 查看指定文件的差异   \ngit diff --stat   # 查看简单的diff结果   \ngit diff          # 比较 Worktree 和 Index 之间的差异   \ngit diff --cached   # 比较Index和HEAD之间的差异   \ngit diff HEAD       # 比较Worktree和HEAD之间的差异   \ngit diff branch     # 比较Worktree和branch之间的差异   \ngit diff branch1 branch2  # 比较两次分支之间的差异   \ngit diff commit commit    # 比较两次提交之间的差异   \ngit diff master..test   # 上面这条命令只显示两个分支间的差异  \ngit diff master...test    # 你想找出‘master’,‘test’的共有 父分支和'test'分支之间的差异，你用3个‘.'来取代前面的两个'.'  \n```\n\n### stash\n\n存储当前的修改，但不用提交 commit\n\n```shell\ngit stash # 将工作区现场（已跟踪文件）储藏起来，等以后恢复后继续工作。  \ngit stash -u    # 保存当前状态，包括 untracked 的文件\ngit stash list  # 查看保存的工作现场   \ngit stash apply # 恢复工作现场   \ngit stash drop  # 删除stash内容\ngit stash clear # 删除所有的 stash\ngit stash pop   # 恢复的同时直接删除stash内容   \ngit stash apply stash@{0} # 恢复指定的工作现场，当你保存了不只一份工作现场时。\ngit checkout \u003cstash@{n}\u003e -- \u003cfile-path\u003e # 从 stash 中拿出某个文件的修改\n```\n\n### merge\n\n```bash\ngit merge --squash test # 合并压缩，将test上的commit压缩为一条   \n```\n\n### cherry-pick\n\n```shell\ngit cherry-pick commit    # 拣选合并，将commit合并到当前分支   \ngit cherry-pick -n commit # 拣选多个提交，合并完后可以继续拣选下一个提交   \n```\n\n### rebase\n\n```shell\ngit rebase master   # 将master分之上超前的提交，变基到当前分支  \ngit rebase --onto master 169a6  # 限制回滚范围，rebase当前分支从169a6以后的提交  \ngit rebase --interactive # 交互模式，修改commit   \ngit rebase --continue    # 处理完冲突继续合并   \ngit rebase --skip        # 跳过   \ngit rebase --abort       # 取消合并    \n```\n\n## 分支branch\n\n### 删除\n\n```shell\ngit push origin :branchName  # 删除远程分支  \ngit push origin --delete new # 删除远程分支new   \ngit branch -d branchName     # 删除本地分支，强制删除用-D  \ngit branch -d test      # 删除本地test分支   \ngit branch -D test      # 强制删除本地test分支   \ngit remote prune origin # 远程删除了，本地还能看到远程存在，这条命令删除远程不存在的分支\n```\n\n### 提交\n\n```bash\ngit push -u origin branchName # 提交分支到远程origin主机中  \n```\n\n### 拉取\n\n```bash\ngit fetch -p # 拉取远程分支时，自动清理 远程分支已删除，本地还存在的对应同名分支。  \ngit fetch origin '+refs/heads/*:refs/heads/*' # 更新所有分支内容\n```\n\n### 分支合并\n\n```shell\ngit merge branchName      # 合并分支 - 将分支branchName和当前所在分支合并   \ngit merge origin/master   # 在本地分支上合并远程分支。   \ngit rebase origin/master  # 在本地分支上合并远程分支。   \ngit merge test            # 将test分支合并到当前分支   \n```\n\n### 重命名\n\n```bash\ngit branch -m old new # 重命名分支  \n```\n\n### 查看\n\n```shell\ngit branch      # 列出本地分支   \ngit branch -r   # 列出远端分支   \ngit branch -a   # 列出所有分支   \ngit branch -v   # 查看各个分支最后一个提交对象的信息   \ngit branch --merge      # 查看已经合并到当前分支的分支   \ngit branch --no-merge   # 查看为合并到当前分支的分支   \ngit remote show origin  # 可以查看remote地址，远程分支\n```\n\n### 新建\n\n```shell\ngit branch test # 新建test分支  \ngit branch newBrach 3defc69 # 指定哈希3defc69，新建分支名字为newBrach\ngit checkout -b newBrach origin/master # 取回远程主机的更新以后，在它的基础上创建一个新的分支  \ngit checkout -b newBrach 3defc69 # 以哈希值3defc69，新建 newBrach 分支，并切换到该分支\n```\n\n### 连接\n\n```shell\ngit branch --set-upstream dev origin/dev     # 将本地dev分支与远程dev分支之间建立链接  \ngit branch --set-upstream master origin/next # 手动建立追踪关系  \n```\n\n### 分支切换\n\n```shell\ngit checkout -        # 快速切换分支上一个分支\ngit checkout test     # 切换到test分支   \ngit checkout -b test  # 新建+切换到test分支   \ngit checkout -b test dev # 基于dev新建test分支，并切换   \n```\n\n## 远端\n\n```shell\ngit fetch \u003c远程主机名\u003e \u003c分支名\u003e   # fetch取回所有分支（branch）的更新  \ngit fetch origin remotebranch[:localbranch]   #  从远端拉去分支[到本地指定分支]   \ngit merge origin/branch   # 合并远端上指定分支   \ngit pull origin remotebranch:localbranch  #  拉去远端分支到本地分支   \ngit push origin branch    # 将当前分支，推送到远端上指定分支   \ngit push origin localbranch:remotebranch  # 推送本地指定分支，到远端上指定分支   \ngit push origin :remotebranch   # 删除远端指定分支   \ngit checkout -b [--track] test origin/dev # 基于远端dev分支，新建本地test分支[同时设置跟踪]  \n```\n\n## submodule\n\n克隆项目同时克隆 submodule\n\n```bash\ngit clone https://github.com/jaywcjlove/handbook.git --depth=1 --recurse-submodules\n```\n\n克隆项目，之后再手动克隆 submodule 子项目\n\n```bash\ngit submodule add -b gh-pages --force '仓库地址' '路径'\ngit submodule add --force '仓库地址' '路径'\n# 其中，仓库地址是指子模块仓库地址，路径指将子模块放置在当前工程下的路径。\n# 注意：路径不能以 / 结尾（会造成修改不生效）、不能是现有工程已有的目录（不能順利 Clone）\ngit submodule init # 初始化 submodule\ngit submodule update # 更新submodule(必须在根目录执行命令)\ngit submodule update --init --recursive  # 下载的工程带有submodule\ngit submodule update --recursive --remote # 对于 git 1.8.2 或更高版本，添加了选项 --remote 以支持更新远程分支\ngit pull --recurse-submodules # 更新 submodule git 1.7.3 版本\n```\n\n当使用`git clone`下来的工程中带有submodule时，初始的时候，submodule的内容并不会自动下载下来的，此时，只需执行如下命令：\n\n```bash\ngit submodule foreach --recursive git submodule init\n```\n\n### 更新 submodule\n\n```bash\ngit submodule foreach git pull  # submodule 里有其他的 submodule 一次更新\ngit submodule foreach git pull origin master # submodule更新\ngit submodule foreach --recursive git submodule update\ngit submodule update --recursive --remote\ngit pull --recurse-submodules\ngit submodule deinit --all -f # 清理 submodule\n```\n\n```bash\ngit clone --recurse-submodules --depth=1 --shallow-submodules https://github.com/example/project.git\n# --depth 选项限制拉取历史记录的数量，以减少克隆所需的时间和空间\n# --shallow-submodules 则限制子模块拉取的历史记录数量，这两者的结合可以在 Git 项目中只拉取代码\n```\n\n### 删除 submodule\n\n```bash\ngit ls-files --stage \u003c子项目名称路径\u003e # 查看子项目\nvim .gitmodules # 删除对应的 submodule\nvim .git/config # 删除对应的 submodule\ngit rm --cached \u003c子模块名称\u003e # 删除缓存中的子项目，注意没有 `/`\ngit rm --cached subProjectName\nrm -rf project/subProjectName\nrm .git/module/* # 删除模块下的子模块目录，每个子模块对应一个目录，注意只删除对应的子模块目录即可\n```\n\n### 转换分支\n\n```bash\n$ git config -f .gitmodules submodule.public.branch gh-pages\n```\n\n下面是更改 `.gitmodules`  文件内容\n\n```\n[submodule \"public\"]\n  path = public\n  url = git@github.com:jaywcjlove/gitke.git\n  branch = gh-pages\n```\n\n## 删除文件\n\n```bash\ngit rm -rf node_modules/\n```\n\n## remote\n\ngit是一个分布式代码管理工具，所以可以支持多个仓库，在git里，服务器上的仓库在本地称之为remote。个人开发时，多源用的可能不多，但多源其实非常有用。  \n\n```shell\ngit remote add origin1 git@github.com:yanhaijing/data.js.git  \ngit remote    # 显示全部源  \ngit remote -v # 显示全部源+详细信息  \ngit remote rename origin1 origin2 # 重命名  \ngit remote rm origin    # 删除  \ngit remote show origin  # 查看指定源的全部信息  \n```\n\n## 标签tag\n\n当开发到一定阶段时，给程序打标签是非常棒的功能。  \n\n```bash\ngit tag -a v0.1.1 9fbc3d0           # 补打 tag，根据 hash 创建 tag\ngit tag -a v0.1 -m 'my version 1.4' # 新建带注释标签   \ngit push origin --tags              # 一次性推送所有分支 \ngit push origin v1.5                # 推送单个tag到orgin源上 \ngit tag -v v1.4.2.1                 # 验证标签，验证已经签署的标签\ngit show v1.5                       # 看到对应的 GPG 签\n\ngit tag        # 列出现有标签   \ngit tag v0gi.1 # 新建标签   \ngit checkout tagname   # 切换到标签       \ngit tag -d v0.1 # 删除标签   \ngit push origin :refs/tags/v0.1 # 删除远程标签   \ngit pull --all # 获取远程所有内容包括tag  \ngit --git-dir='\u003c绝对地址\u003e/.git' describe --tags HEAD # 查看本地版本信息  \n```\n\n### 重命名Tag\n\n```bash\nmv .git/refs/tags/1.9.1 .git/refs/tags/v1.9.1\ngit push -f --tags\n```\n\n## 日志log\n\n```bash\ngit config --global format.pretty \"%Cgreen%h%Creset %s %Cblue@%cn%Creset %Cred%ai%Creset\" # 全局配置彩色 log 输出\ngit config --global format.pretty \"%h: %s @%cn %ai\" # 全局配置格式化后的 log\ngit config format.pretty oneline  # 显示历史记录时，每个提交的信息只显示一行   \ngit config color.ui true # 彩色的 git 输出   \ngit log # 查看最近的提交日志\ngit log --grep=224 # 这条命令是查看含有 \"224\" 关键字的 git commit \ngit log --pretty=oneline # 单行显示提交日志   \ngit log --graph --pretty=oneline --abbrev-commit   \ngit log -num # 显示第几条log（倒数）   \ngit reflog   # 查看所有分支的所有操作记录   \ngit log --since=1.day # 一天内的提交；你可以给出各种时间格式，比如说具体的某一天（“2008-01-15”），或者是多久以前（“2 years 1 day 3 minutes ago”）。   \ngit log --pretty=\"%h - %s\" --author=自己的名字 # 查看自己的日志   \ngit log -p -2  # 展开两次更新显示每次提交的内容差异   \ngit log --stat # 要快速浏览其他协作者提交的更新都作了哪些改动   \ngit log --pretty=format:\"%h - %an, %ar : %s\"# 定制要显示的记录格式   \ngit log --pretty=format:'%h : %s' --date-order --graph # 拓扑顺序展示   \ngit log --pretty=format:'%h : %s - %ad' --date=short   # 日期YYYY-MM-DD显示\ngit log --pretty=oneline --graph --decorate --all # 展示简化的 commit 历史\ngit log \u003clast tag\u003e HEAD --pretty=format:%s # 只显示commit   \ngit config --global format.pretty '%h : %s - %ad' --date=short #日期YYYY-MM-DD显示 写入全局配置\n```\n\n|选项 | 说明|选项 | 说明|\n|----|----|----|----|\n|%H  |提交对象（commit）的完整哈希字串 |%ad |作者修订日期（可以用 -date= 选项定制格式）|\n|%h  |提交对象的简短哈希字串 |%ar |作者修订日期，按多久以前的方式显示|\n|%T  |树对象（tree）的完整哈希字串 |%cn |提交者(committer)的名字|\n|%t  |树对象的简短哈希字串 |%ce |提交者的电子邮件地址|\n|%P  |父对象（parent）的完整哈希字串 |%cd |提交日期|\n|%p  |父对象的简短哈希字串 |%cr |提交日期，按多久以前的方式显示|\n|%an |作者（author）的名字 |%s  |提交说明|\n|%ae |作者的电子邮件地址| - | - |\n\n[Pretty Formats](https://git-scm.com/docs/git-log#_pretty_formats)\n\n## 重写历史\n\n```bash\ngit commit --amend    # 改变最近一次提交  \ngit rebase -i HEAD~3  # 修改最近三次的提交说明，或者其中任意一次  \ngit commit --amend    # 保存好了，这些指示很明确地告诉了你该干什么  \ngit rebase --continue # 修改提交说明，退出编辑器。  \n```\n\n```bash\npick f7f3f6d changed my name a bit\npick 310154e updated README formatting and added blame\npick a5f4a0d added cat-file\n```\n\n改成\n\n```\npick 310154e updated README formatting and added blame\npick f7f3f6d changed my name a bit\n```\n\n## 其它\n\n```bash\ngit help *  # 获取命令的帮助信息  \ngit status  # 获取当前的状态，非常有用，因为git会提示接下来的能做的操作  \n```\n\n\n## 报错问题解决\n\n**1. `git fatal: protocol error: bad line length character: No s`**\n\n解决办法：更换remote地址为 `http/https` 的  \n\n**2. `The requested URL returned error: 403 Forbidden while accessing`**\n\n解决github push错误的办法：\n\n```shell\n#vim 编辑器打开 当前项目中的config文件\nvim .git/config\n\n#修改\n[remote \"origin\"]  \n    url = https://github.com/jaywcjlove/example.git  \n\n#为下面代码\n[remote \"origin\"]  \n    url = https://jaywcjlove@github.com/jaywcjlove/example.git  \n```\n\n**3. git status 显示中文问题**\n\n在查看状态的时候 git status 如果是中文就显示下面的情况\n\n```bash\n\\344\\272\\247\\345\\223\\201\\351\\234\\200\\346\\261\\202\n```\n\n解决这个问题方法是：\n\n```bash\ngit config --global core.quotepath false\n```\n\n**4. The authenticity of host 192.168.0.xxx can't be establis**\n\n修改 `/etc/ssh/ssh_config` 中的 `StrictHostKeyChecking` 的 `ask` 为 `no` 解决问题。\n\n**5. SSH连接时出现 Host key verification failed 的原因及解决方法**\n\n用 OpenSSH 的人都知 ssh 会把你每个你访问过计算机的公钥(public key)都记录在~/.ssh/known_hosts。当下次访问相同计算机时，OpenSSH 会核对公钥。如果公钥不同，OpenSSH 会发出警告，避免你受到 DNS Hijack 之类的攻击。\nSSH 对主机的 public_key 的检查等级是根据\n\n```bash\nStrictHostKeyChecking=no  # 最不安全的级别，当然也没有那么多烦人的提示了，相对安全的内网测试时建议使用。如果连接server的key在本地不存在，那么就自动添加到文件中（默认是known_hosts），并且给出一个警告。\nStrictHostKeyChecking=ask # 默认的级别，就是出现刚才的提示了。如果连接和key不匹配，给出提示，并拒绝登录。\nStrictHostKeyChecking=yes # 最安全的级别，如果连接与key不匹配，就拒绝连接，不会提示详细信息。\n```\n\n【解决方法1】在 `.ssh/config`（或者`/etc/ssh/ssh_config`）中配置：\n\n```conf\nStrictHostKeyChecking no\nUserKnownHostsFile /dev/null\n```\n\n解决方法 2\n\n```bash\nvi ~/.ssh/known_hosts # 删除对应ip的相关rsa信息\nrm known_hosts # 或者直接全部删除\n```\n\n**5. insufficient permission for adding an object to repository database .git/objects**\n\n```\ncd .git/objects\nls -al\nsudo chown -R yourname:yourgroup *\n```\n\n## 参考资料\n\n- [Git官网](http://git-scm.com/)\n- [**Github 15分钟学习Git**](https://try.github.io)\n- [Git参考手册](http://gitref.org/zh/index.html)\n- [Git简明手册](http://www.mceiba.com/tool/git-cheat-sheet.html)\n- [Git Magic](http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/)\n- [Git Community Book 中文版](http://gitbook.liuhui998.com/index.html)\n- [Pro Git](http://git-scm.com/book/en/v2)\n- [图解Git](http://marklodato.github.io/visual-git-guide/index-zh-cn.html)\n- [git-简明指南](http://rogerdudler.github.io/git-guide/index.zh.html)\n- [learnGitBranching 在线学习工具](http://pcottle.github.io/learnGitBranching/)\n- [初级教程](http://rogerdudler.github.io/git-guide/index.zh.html) \n- [廖雪峰的Git教程](http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000)\n- [蒋鑫老师将带你入github的大门](http://www.worldhello.net/gotgithub/)\n- [git详解](http://www.open-open.com/lib/view/open1328069609436.html)\n- [oschina教程](http://git.oschina.net/progit/)\n- [How to undo (almost) anything with Git撤销一切，汇总各种回滚撤销的场景，加强学习。](https://github.com/blog/2019-how-to-undo-almost-anything-with-git)\n- [Git 教程 | 菜鸟教程runoob.com](http://www.runoob.com/git/git-tutorial.html)\n- [Git 本地仓库和裸仓库](https://gold.xitu.io/post/5842f9b861ff4b005889ade6)\n- [沉浸式学 Git](http://www.kancloud.cn/kancloud/igit/46710)\n- [Git进阶用法，主要是rebase高级用法](http://way.oschina.io/2016/12/15/notes/GitAdvance/?utm_source=gank.io\u0026utm_medium=email)\n- [成为一个git大师](https://www.atlassian.com/git/tutorials)\n- [高质量的Git中文教程](https://github.com/geeeeeeeeek/git-recipes)\n\n## Contributors\n\nAs always, thanks to our amazing contributors!\n\n\u003ca href=\"https://github.com/jaywcjlove/git-tips/graphs/contributors\"\u003e\n  \u003cimg src=\"https://jaywcjlove.github.io/git-tips/CONTRIBUTORS.svg\" /\u003e\n\u003c/a\u003e\n\nMade with [action-contributors](https://github.com/jaywcjlove/github-action-contributors).\n\n## License\n\nMIT © [Kenny Wong](https://github.com/jaywcjlove)\n","funding_links":["https://ko-fi.com/jaywcjlove","https://buymeacoffee.com/jaywcjlove","https://www.paypal.me/kennyiseeyou","https://jaywcjlove.github.io/#/sponsor"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaywcjlove%2Fgit-tips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaywcjlove%2Fgit-tips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaywcjlove%2Fgit-tips/lists"}