diff --git a/doc/git-rebase合并多条commit记录实操.pdf b/doc/git-rebase合并多条commit记录实操.pdf deleted file mode 100644 index 97e45a1..0000000 Binary files a/doc/git-rebase合并多条commit记录实操.pdf and /dev/null differ diff --git a/doc/git/git-commit-standardize.md b/doc/git/git-commit-standardize.md new file mode 100644 index 0000000..80151ac --- /dev/null +++ b/doc/git/git-commit-standardize.md @@ -0,0 +1,67 @@ +### 背景 + +Git每次提交代码都需要写commit message,否则就不允许提交。一般来说,commit message应该清晰明了,说明本次提交的目的,具体做了什么操作……但是在日常开发中,大家的commit message千奇百怪,中英文混合使用、fix bug等各种笼统的message司空见怪,这就导致后续代码维护成本特别大,有时自己都不知道自己的fix bug修改的是什么问题。基于以上这些问题,我们希望通过某种方式来监控用户的git commit message,让规范更好的服务于质量,提高大家的研发效率。 + +### 规范建设 + +#### 规范梳理 + +初期我们在互联网上搜索了大量有关git commit规范的资料,但只有Angular规范是目前使用最广的写法,比较合理和系统化,并且有配套的工具(IDEA就有插件支持这种写法)。最后综合阿里巴巴高德地图相关部门已有的规范总结出了一套git commit规范。 + +## **commit message格式** + +```plain +(scope): +``` +## type (必须) + +用于说明git commit的类别,只允许使用下面的标识。 + +feat:新功能(feature)。 + +fix/to:修复bug,可以是QA发现的BUG,也可以是研发自己发现的BUG。 + +* fix:产生diff并自动修复此问题。适合于一次提交直接修复问题 +* to:只产生diff不自动修复此问题。适合于多次提交。最终修复问题提交时使用fix +docs:文档(documentation)。 + +style:格式(不影响代码运行的变动)。 + +refactor:重构(即不是新增功能,也不是修改bug的代码变动)。 + +perf:优化相关,比如提升性能、体验。 + +test:增加测试。 + +chore:构建过程或辅助工具的变动。 + +revert:回滚到上一个版本。 + +merge:代码合并。 + +sync:同步主线或分支的Bug。 + +## scope (可选) + +scope用于说明 commit 影响的范围,比如数据层、控制层、视图层等等,视项目不同而不同。 + +例如在Angular,可以是location,browser,compile,compile,rootScope, ngHref,ngClick,ngView等。如果你的修改影响了不止一个scope,你可以使用*代替。 + +## subject (必须) + +ubject是commit目的的简短描述,不超过50个字符。 + +建议使用中文(感觉中国人用中文描述问题能更清楚一些)。 + +* 结尾不加句号或其他标点符号。 +* 根据以上规范git commit message将是如下的格式: +```plain +fix(DAO):用户查询缺少username属性 +feat(Controller):用户查询接口开发 +``` +以上就是我们梳理的git commit规范,那么我们这样规范git commit到底有哪些好处呢? +* 便于程序员对提交历史进行追溯,了解发生了什么情况。 +* 一旦约束了commit message,意味着我们将慎重的进行每一次提交,不能再一股脑的把各种各样的改动都放在一个git commit里面,这样一来整个代码改动的历史也将更加清晰。 +* 格式化的commit message才可以用于自动化输出Change log。 + + diff --git a/doc/git/git-rebase.md b/doc/git/git-rebase.md new file mode 100644 index 0000000..976b561 --- /dev/null +++ b/doc/git/git-rebase.md @@ -0,0 +1,41 @@ + +## git rebase 合并多条 commit 记录 + +### PS:gedit 不太好用,可以执行如下命令将编辑器修改为熟悉的 vim +```shell +git config --global core.editor "vim" +``` + +如图,我们有一些 commit 是比较凌乱的,现在希望将其整理为一条合适的 commit 提交到 远程仓库。 + +![git log](pic/p1.jpg) +我们需要将 day1 day2 add file 这三条记录合并为一条,执行 + +```shell +git rebase -i [commit] +``` + **commit** 为你要合并的最后一条提交的下一个 commit, + + 这里为 640f9a20c7bb7e9e3dfc76b089745d5c95818fed + +指令如下 +```shell +git rebase -i 640f9a20c7bb7e9e3dfc76b089745d5c95818fed +``` +![git rebase](pic/p2.jpg) + +这里将弹出 vim 编辑窗口,可以看到有此次 rebase 涉及到三个 commit id,我们选取需要 pick 的 commit id,其余的参考下面注释,添加 s 前缀,表示 commit 用于提交但是归并到 pick 的 commit 中。 + +:wq 保存,将进入下一个 vim 编辑界面 +![:wq 保存](pic/p3.jpg) + +将所有的 commit msg 编辑一个合适的归并 commit msg。 +再次执行 :wq 保存即可。 +![再次执行 :wq保存](pic/p4.jpg) +可以看到,我们将两条不希望留存的 commit 记录归并到了 +![rebase后效果](pic/p5.jpg) + + +640f9a20c7bb7e9e3dfc76b089745d5c95818fed 提交之中,并且,这样的操作并不会改变原本这个 commit id 的值。 + +PS: 具体 rebase 指令细节参考 ```git rebase --help``` \ No newline at end of file diff --git a/doc/git/git.md b/doc/git/git.md new file mode 100644 index 0000000..4d28abd --- /dev/null +++ b/doc/git/git.md @@ -0,0 +1,299 @@ +# git初步使用 + +``` +git init + +//设置仓库的公共信息,这个user信息会体现在commit信息中 +git config --global user.name "yourname" +git config --global user.email "your email" + +//在远程仓库方面,有两种模式,一种ssh一种https +//https 简单方便,但每次push都要输入密码 + +git remote add origin https://github.com/yourgit/your warehouse.git + +git add --all +git commit -m "you commit info" +git push -u origin master //第一次,以后可以用git push简化 + +//ssh模式 需要先在github中添加自己的sshkey + +//首先看自己的本地目录下是否有 .ssh目录 +//没有的话 +ssh-keygen -t rsa -C "youremail@example.com" +//并将 .ssh/id_rsa.pub中的key添加到github.com中 + +git remote add origin git@github.com:yourgit/your warehouse.git + +``` + +## git alias + ~/.gitconfig配置文件可以配置当前用户全局git属性,当然每个字母了git仓库下也可以有一个.gitconfig配置当前仓库属性,属性中有一个alias属性来给git一些命令提供别名,方便使用 + +配置方法参考 ```git config --help``` + +下面给出我的配置仅供参考 + + ```shell +[user] + email = liaojia138797@163.com + name = ljx +[alias] + st = status + co = checkout + br = branch + hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short + type = cat-file -t + dump = cat-file -p + cm = commit -m + df = diff + +[core] + editor = vim + ``` + +## gitignore + +``` + 所有空行或者以注释符号 # 开头的行都会被 Git 忽略。 + 可以使用标准的 glob 模式匹配。 + 匹配模式最后跟反斜杠(/)说明要忽略的是目录。 + 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。 + + 所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(*)匹配零个或多个任意字符;[abc]匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 +``` +## git命令 + +* git rm / git rm --cached +``` +//当我们要删除文件filename, 并且工作区也不需要这个文件了 +git rm filename + +//当我们需要删除暂存区或者分支的文件,但是本地需要保留这个文件,只是不希望此文件被版本控制时 +git rm --cached filename +``` +* git branch +``` +查看本地分支:$ git branch +查看远程分支:$ git branch -r +创建本地分支:$ git branch [name] ----注意新分支创建后不会自动切换为当前分支 +切换分支:$ git checkout [name] +创建新分支并立即切换到新分支:$ git checkout -b [name] +删除分支:$ git branch -d [name] ---- -d选项只能删除已经参与了合并的分支,对于未有合并的分支是无法删除的。如果想强制删除一个分支,可以使用-D选项 +合并分支:$ git merge [name] ----将名称为[name]的分支与当前分支合并 +创建远程分支(本地分支push到远程):$ git push origin [name] +删除远程分支:$ git push origin :heads/[name]  +或 $ git push origin :[name]  +``` +* git remote +```c++ +查看远程仓库:$ git remote -v +添加远程仓库:$ git remote add [name] [url] +删除远程仓库:$ git remote rm [name] +修改远程仓库:$ git remote set-url --push [name] [newUrl] +拉取远程仓库:$ git pull [remoteName] [localBranchName] +推送远程仓库:$ git push [remoteName] [localBranchName] +  +*如果想把本地的某个分支test提交到远程仓库,并作为远程仓库的master分支,或者作为另外一个名叫test的分支,如下: +$git push origin test:master   // 提交本地test分支作为远程的master分支 +$git push origin test:test     // 提交本地test分支作为远程的test分支 +``` +* git merge +``` +//合并a分支到master +git checkout master +git merge a + +``` +* git tag +``` +//标签 +git tag v1.0 +``` +* git reset +``` +当将不想staging的文件add进了index,可以 +git reset HEAD +git reset --hard xxx +xxx可以是connid,可以退回到此id的版本 +hard (修改版本库,修改暂存区,修改工作区) +--hard HEAD~1 (或是commid)意为将版本库回退1个版本,但是不仅仅是将本地版本库的头指针全部重置到指定版本,也会重置暂存区,并且会将工作区代码也回退到这个版本 +这个操作非常危险,需要谨慎执行,如果不小心丢失掉了一些commit的话,执行 +git reflog找到丢失掉的commit再次git reset --hard 回去 + +git reset --soft xxx +soft (修改版本库,保留暂存区,保留工作区) +--soft HEAD~1 意为将版本库软回退1个版本,所谓软回退表示将本地版本库的头指针全部重置到指定版本,且将这次提交之后的所有变更都移动到暂存区。 +意思是当你commit后,又执行 git reset --soft HEAD^1,你本次commit直接从repository退回到index,未commit状态,如果是退回多个版本,则多次commit回退 + +不加参数(--mixed)  +意思是:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作 +这个为默认参数,git reset --mixed HEAD^ 和 git reset HEAD^ 效果是一样的。 + + + +git revert xxx +revert +-- git revert 也是撤销命令,区别在于reset是指向原地或者向前移动指针,git revert是创建一个commit来覆盖当前的commit,指针向后移动。 + +https://www.jianshu.com/p/c2ec5f06cf1a + +git reset --hard : +1.替换引用的指向.引用指向新的提交ID; +2.替换暂存区.替换后,暂存区的内容和引用指向的目录树一致; +3.替换工作区.替换后,工作区的内容变得和暂存区一致,也和HEAD所指向的目录树内容相同. + +git reset --soft : +1.替换引用的指向.引用指向新的提交ID. +即只更改引用的指向,不该编暂存区和工作区. + +git reset --mixed 或git reset : +1.替换引用的指向.引用指向新的提交ID; +2.替换暂存区.替换后,暂存区的内容和引用指向的目录树一致; +即更改引用的指向及重置暂存区,但是工作区不变. + +实例: +git reset +仅用HEAD指向的目录树重置暂存区,工作区不受影响,相当于将之前用git add命令更新到暂存区的内容撤出暂存区.引用也未改变,因为引用重置到HEAD相当于没有重置. + +git reset HEAD +同上 + +git reset -- filename +仅将文件filename的改动撤出暂存区,暂存区中其他文件不该变.相当于git add filename的反向操作. + +git reset HEAD filename +同上 + +git reset --soft  HEAD^ +工作区和暂存区不改变,但是引用向前回退一次.当对最新提交的提交说明或提交不满意更改时,撤销最新的提交一遍重新提交. + +git reset HEAD^ +工作区不变,但是暂存区会回退到上一次提交之前,引用也会回退一次. + +git reset --mixed HEAD^ +同上 + +git reset --hard HEAD^ +彻底撤销最近的提交.引用回退到前一次,而且工作区和暂存区都会回退到上一次提交的状态.自上一次以来的提交全部丢失. +``` +* git checkout +``` +git  checkout  +git checkout [--] +1.是可选项,如果省略则相当于从暂存区进行检出.和reset命令大不相同:重置的默认值是HEAD,而检出的默认值是暂存区. +2.因此重置一般用于重置暂存区(除非使用--hard,否则不重置工作区),而检出命令主要是覆盖工作区(如果不省略,也会替换暂存区中相应的文件). +3.该命令不会改变HEAD的头指针,主要用于指定版本文件覆盖工作区中对应的文件.如果省略,则会用暂存区的文件覆盖工作区的文件,否则用指定提交中的文件覆盖暂存区和工作区中的对应文件. + +git checkout   + +1.会改变HEAD头指针.之所以后面的参数写作,是因为只有HEAD切换到一个分支才可以对提交进行跟踪,否则仍然会进入"分离头指针"的状态.在"分离头指针"的状态下的提交并不能被引用关联到,从而可能丢失.所以该命令主要作用是切换分支. +2.如果省略则相当于对工作区进行状态检查. + +实例: +git checkout branch +检出branch分支,更新HEAD以指向branch分支,以及用branch指向的树更新暂存区和工作区. + +git checkout +汇总显示工作区,暂存区与HEAD的差异 + +git checkout HEAD +同上 + +git checkout -- filename +用暂存区中的filename文件来覆盖工作区中的filename文件.相当于取消自上次执行git add filename以来(如果执行过)的本地修改 +//放弃修改回到以前的状态 +//这条命令有些危险,所有对文件的修改都没有了,因为我们刚刚把之前版本的文件复制过来重写了此文件。所以在用这条命令前,请务必确定真的不再需要保留刚才的修改 + +git checkout branch -- filename +维持HEAD的指向不变.用branch所指向的提交中的filename替换暂存区和工作区中相应的文件.会将暂存区和工作区中的filename直接覆盖 + +git checkout -- .或者git checkout . +会取消本地所有修改,相当于用暂存区的所有文件直接覆盖本地文件. +``` +* git stash +``` +当你做某个工作时遇到紧急情况需要切换branch,又不想commit当前未完成工作来造成不必要的繁琐log时,执行 +git stash +或者执行 +git stash save "something" +当你完成紧急工作后想要继续当时停下来的开发 +在原分支 git stash save -a "messeag",网上很多很多资料都没有加 -a 这个option选项,我想他们的代码开发可能都是在原代码上进行修改吧。而对于在项目里加入了代码新文件的开发来说,-a选项才会将新加入的代码文件同时放入暂存区。 + +git stash pop可以弹回到最后一次的stash +也可以 +git stash list查看有几个stash +git stash apply stash@{}来回到你想要的stash +git stash clear清除所有缓存的stash +git stash show stash@{}来查看diff + +stash信息不回被删除,除非你弹回去了,但如果你不想要那时候的stash了。比如认为当时的改动是错误的,你可以 +git stash drop  如果不加stash编号,默认的就是删除最新的,也就是编号为0的那个,加编号就是删除指定编号的stash。git  stash clear 是清除所有stash,整个世界一下子清净了! +git stash pop  与 git stash apply  的区别。 +当我使用git stash pop 和 git stash apply 几次以后,我发现stash  list 好像比我预计的多了几个stash。于是我便上网去了解了一下这两个命令的区别。原来git stash pop stash@{id}命令会在执行后将对应的stash id 从stash list里删除,而 git stash apply stash@{id} 命令则会继续保存stash id。对于有点强迫症的我来说,是容不下越来越多的陈旧stash id 仍然存在的,所以我更习惯于用git stash pop 命令。 +``` +* git log +``` +$ git log -p -2 +//我们常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新 +$ git log -U1 --word-diff +//上下文行数1行,以单词来看差异,单词前后以+wold+ - - 表示出来 +``` +* git commit +``` +$ git commit amend +//有时候我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以使用 --amend 选项重新提交 +``` +* git clone +``` +git clone git@github.com:ljx791863565/xxx.git +git clone https://github.com/ljx791863565/xxx.git +``` +* git diff +``` +//比较暂存区与版本库的改动 +git diff --staged + +git diff commid1 commid2 +git diff branch1 branch2 + +git diff : 对比工作区(未 git add)和暂存区(git add 之后) +git diff --cached: 对比暂存区(git add 之后)和版本库(git commit 之后) +git diff HEAD: 对比工作区(未 git add)和版本库(git commit 之后) + +``` +* git config +Git 提供了一个叫做 git config 的工具(译注:实际是 git-config 命令,只不过可以通过 git 加一个名字来呼叫此命令。),专门用来配置或读取相应的工作环境变量。而正是由这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方: + + * /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system选项,读写的就是这个文件。 + * ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global选项,读写的就是这个文件。 +当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。 + +供了一个叫做 git config 的工具(译注:实际是 git-config 命令,只不过可以通过 git 加一个名字来呼叫此命令。),专门用来配置或读取相应的工作环境变量。而正是由这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方: + + * /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system选项,读写的就是这个文件。 + * ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global选项,读写的就是这个文件。 +当前项目的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。 + +``` +第一个要配置的是你个人的用户名称和电子邮件地址。这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录: +$ git config --global user.name "John Doe" +$ git config --global user.email johndoe@example.com +如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。 + +还有一个比较常用的是,在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话: +$ git config --global merge.tool vimdiff +Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。当然,你也可以指定使用自己开发的工具 + +``` +## git问题解决 + +* fatal: object 906d1543778b940af481c0ca7f5ce9d3d9771140 is corrupted +``` +rm -rf .git +git init +git remote add origin git@github.com:yourgit/yourwarehouse.git +git fetch +git reset --hard origin/master +``` +[https://blog.csdn.net/dengjianqiang2011/article/details/9260435](https://blog.csdn.net/dengjianqiang2011/article/details/9260435) diff --git a/doc/git/pic/p1.jpg b/doc/git/pic/p1.jpg new file mode 100644 index 0000000..4fc952a Binary files /dev/null and b/doc/git/pic/p1.jpg differ diff --git a/doc/git/pic/p2.jpg b/doc/git/pic/p2.jpg new file mode 100644 index 0000000..c16753c Binary files /dev/null and b/doc/git/pic/p2.jpg differ diff --git a/doc/git/pic/p3.jpg b/doc/git/pic/p3.jpg new file mode 100644 index 0000000..2d8080d Binary files /dev/null and b/doc/git/pic/p3.jpg differ diff --git a/doc/git/pic/p4.jpg b/doc/git/pic/p4.jpg new file mode 100644 index 0000000..1eba0e6 Binary files /dev/null and b/doc/git/pic/p4.jpg differ diff --git a/doc/git/pic/p5.jpg b/doc/git/pic/p5.jpg new file mode 100644 index 0000000..3923ed0 Binary files /dev/null and b/doc/git/pic/p5.jpg differ