学习Git有一段时间了,一路上也一直在写有关于Git方面的文章,但总觉得不是我想要的,就是感觉有点肉肉的,不够直接,不够马上出效果,所以才有了这篇文章,当然这文章可能会不断更新和修正,希望读者可以作为一个工具文章使用,我也会努力将其优化的更加的符合工作场景
说明
1、在[…]中的内容,需要根据实际情况进行修改
如何本地与远程建立信任联系?
要解决这个问题,需要使用SSH秘钥的方式,接下来我就讲一下怎么进行配置。
1.在本地生成私钥和公钥
1 | git config --global user.name "username"//用户昵称 |
2.将电脑上的公钥与远程仓库进行绑定
本地会在上面的步骤中会生成一个id_rsa.pub(默认情况是这个名称),将该文件中的内容copy到远程仓库github或gitlib的settings的SSH配置选项中。
Tittle名称自由发挥
克隆工程
将远程的数据复制一份到本地
1 | 【仓库copy地址】 |
本地新建Git工程
现在打算将本地的工程,放到Git仓库进行托管了,并且远程Git仓库已经创建了该项目的工程
1 | 本地初始化工程,会生成一个.git文件 |
显示某一个特定的提交的日志
1 | git show [十六进制码] |
查看提交图
1 | git log --graph --pretty=oneline --abbrev-commit |
查看冲突未处理的文件列表
1 | git ls-files -u |
本地代码与远程代码冲突问题
本地代码未commit的前提下,解决与远程代码冲突问题
1 | git pull #失败 |
但,上面的也可能存在问题,由于本地存在未被追踪的文件,并且远程仓库pull的时候也存在同名的文件,就会存在pull失败,在这种情况下,在
git stash
后面追加--include-untracked
,会将远程的文件与本地的文件融合stash只会保存当前索引和工作目录的状态,其保存的是add和commit的中间状态,如果还没有被git追踪的文件,是不会被记录的
stash只保存被修改的文件内容,未被修改的文件内容不会被记录,在apply恢复的时候,也只会更新 stash 时被保存的内容
如果我对某文件进行了修改,但我不想要push到远程仓库,同时我又想获取最新的修改记录
1 | git stash save |
如果暂存内容现在不想在当前分支恢复了,而是想单独起一个分支
1 | git stash branch [newBranchName] |
想要查看当前工作区与暂存状态内容区别
1 | git stash show -p stash{0} |
本地代码已经commit后,解决与远程代码冲突问题
1 | 获取远端库最新信息 【分支名称】 |
方法2
1 | 获取最新代码到tmp分支上 [远程的分支:本地分支] |
删除文件
保留副本操作
1 | git rm --cache [文件名] |
直接文件删除
1 | git rm [文件名] |
后悔药
还原到最近的版本,废弃本地做的修改(当前文件修改没有进行add操作的时候)
1 | git checkout -- [文件名] |
取消已经暂存的文件(撤销先前”git add”的操作)
1 | 当前HEAD,返回到上一次commit点,不会有任何日志记录 |
1 | git reset HEAD [文件名] |
回退所有内容到上一个提交点
1 | 最近内容已经commit的情况下 |
回退这个文件的版本到上一个版本
1 | 最近内容已经commit的情况下 |
将本地的状态回退到和远程的一样
1 | git reset –-hard origin/[分支名] |
回退到某个版本
1 | 获取所有的HEAD更改信息的sha1值 |
回退到上一次提交的状态,按照某一次的commit完全反向的进行一次commit.(代码回滚到上个版本,并提交git)
1 | git revert HEAD |
使用reset是不会有日志记录的,revert则会要提交一个记录点
修改最新的提交信息(修改提交的注释信息)
1 | git commit --amend |
reset与revert的使用说明
reset一般用于本地还没有push到远端的时候,revert则用于想要远端也进行记录回退操作的时候,也就是说在push之后。
1、如果你已经push到远程仓库,reset删除指定commit以后,你git push可能导致一大堆冲突.但是revert 并不会
2、如果现有分支和历史分支需要合并的时候,reset 恢复部分的代码依然会出现在历史分支里.但是revert 方向提交的commit 并不会出现在历史分支里。
本地分支与远程分支相连
本地创建了一个分支,远程也有一个分支,进行两者关联
1 | git checkout -b [本地分支名] origin/[远程分支名] |
Tag使用
我们在开发的时候,可能存在线上发布了一个版本,需要给这个版本代码打上一个标签,到时候可以方便回退到这个版本
1 | 创建tag 【tag名】 |
接下来就讲解回退到具体的tag
1 | 保存当前编程环境 |
切换回主干或其他分支
1 | 切换分支 |
分支与主干合并
1 | git add . |
关于代码的比较
1 | 显示暂存区和工作区的差异 |
定位哪个提交点导致文件出现问题
1 | 先确定范围 |
检查文件中每一行代码是谁提交的记录
1 | git blame -L [起始行数],[文件名] |
创建分支
1 | 以当前节点作为分支的开始起点 |
拉去远程仓库分支代码
1 | git checkout 1.0 |
开发的过程中生成新分支
1 | 因可能存在未被git监管和未提交的内容,需要将未提交的内容进行监管和暂存 |
重命名分支
在git中重命名远程分支,其实就是先删除远程分支,然后重命名本地分支,再重新提交一个远程分支。
1 | //显示现在分支 |
这是由于在 github 中,devel 是项目的默认分支。要解决此问题,这样操作:
- 进入 github 中该项目的 Settings 页面;
- 设置 Default Branch 为其他的分支(例如 master);
- 重新执行删除远程分支命令。
查看远程仓库分支
1 | git branch -a |
根据远程仓库分支代码创建分支
1 | git fetch origin [远程仓库分支名:远程仓库分支名] [本地仓库分支名:本地仓库分支名] |
删除本地分支
1 | git branch -d [分支名] |
删除远程仓库分支
1 | git remote remove [分支名] |
查看分支
1 | git show-branch |
分支前面都存在*或者!
*表示当前分支
在–之后的是记录分支的提交信息
像
*+ [tmp] 远程2
就表示该提交存在于两个分支中
显示某分支中某文件内容
1 | git show [分支名]:[文件名] |
显示某个节点某文件的内容
1 | git show [SHA1] [文件名] |
查看本地Git绑定的远程仓库信息
1 | git remote -v |
关于切换分支的逻辑
如果存在未被git追踪的文件,git是会将其忽略的
如果存在已追踪且被修改或删除,必须commit之后,才能切换
如果要不计后果的情况,强切,加
-f
将当前的分支修改的内容同步到其他的分支上
假如你希望变更作用于另一个分支上,但由于当前分支如果不提交,是无法切换到另一个分支上的
1 | git checkout -m [另一个分支名] |
将一个区间的提交,移植到另一个分支
1 | 当前分支,得到dev分支中dev~2之前的所有提交内容 |
cherry-pick会生成一条新的提交记录
代码行数统计
统计某人的代码提交量,包括增加,删除:
1 | git log --author="$(git config --get user.name)" --pretty=tformat: --numstat | gawk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "added lines: %s removed lines : %s total lines: %s\n",add,subs,loc }' - |
统计某人一个月内的代码提交量,包括增加,删除:
1 | git log --since=1.month.ago --author="$(git config --get user.name)" --pretty=tformat: --numstat | gawk '{ add += $1 ; subs += $2 ; loc += $1 - $2 } END { printf "added lines: %s removed lines : %s total lines: %s\n",add,subs,loc }' - |
仓库提交者排名前 5(如果看全部,去掉 head 管道即可):
1 | git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5 |
仓库提交者(邮箱)排名前 5:这个统计可能不会太准,因为很多人有不同的邮箱,但会使用相同的名字
1 | git log --pretty=format:%ae | gawk -- '{ ++c[$0]; } END { for(cc in c) printf "%5d %s\n",c[cc],cc; }' | sort -u -n -r | head -n 5 |
贡献者统计:
1 | git log --pretty='%aN' | sort -u | wc -l |
提交数统计:
1 | git log --oneline | wc -l |
git log 参数说明:
–author 指定作者
–stat 显示每次更新的文件修改统计信息,会列出具体文件列表
–shortstat 统计每个commit 的文件修改行数,包括增加,删除,但不列出文件列表:
–numstat 统计每个commit 的文件修改行数,包括增加,删除,并列出文件列表:-p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新
例如:git log -p -2
–name-only 仅在提交信息后显示已修改的文件清单
–name-status 显示新增、修改、删除的文件清单
–abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符
–relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)
–graph 显示 ASCII 图形表示的分支合并历史
–pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)
例如: git log –pretty=oneline ; git log –pretty=short ; git log –pretty=full ; git log –pretty=fuller
–pretty=tformat: 可以定制要显示的记录格式,这样的输出便于后期编程提取分析
例如:git log –pretty=format:””%h - %an, %ar : %s””
下面列出了常用的格式占位符写法及其代表的意义。
选项 说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明
–since 限制显示输出的范围,
例如: git log –since=2.weeks 显示最近两周的提交
选项 说明
-(n) 仅显示最近的 n 条提交
–since, –after 仅显示指定时间之后的提交。
–until, –before 仅显示指定时间之前的提交。
–author 仅显示指定作者相关的提交。
–committer 仅显示指定提交者相关的提交。
一些例子: git log –until=1.minute.ago // 一分钟之前的所有 log git log –since=1.day.ago //一天之内的log git log –since=1.hour.ago //一个小时之内的 log git log –since=`.month.ago –until=2.weeks.ago //一个月之前到半个月之前的log git
log –since ==2013-08.01 –until=2013-09-07 //某个时间段的 log git blame
看看某一个文件的相关历史记录
例如:git blame index.html –date short
子模块
保留子组件的现有目录结构的完整性,故而git创造了类似于maven中的module一样的功能,来实现子模块的管理
打个比方:现在我有一个父工程A,其工程路径下面有五个子工程BCDEF,按照往常是要git clone
6个工程才可以完全下载成功,而且工程与工程之间的路径关系也不知道。现在有了gitmodules就可以直接下载A工程就可以了,其他的5个子工程都会自动下载。
文件.gitmodules存放在父工程根目录下
1 | [submodule "others/B"] |
添加子模块
1 | git submodule add [远程仓库地址] [相对于父模块的相对路径] |
注:
直接手动更改gitmodule文件是没有用的哦
远程仓库地址要先于子模块之前准备好
子模块的名称是可以与[相对于父模块的相对路径]不一致的
创建完成以后会生成.gitmodules
与.gitattributes
这两个文件
.gitmodules
和.git/config
保存着子模块的信息
从远程仓库获取所有模块数据
1 | 方式一 |
删除子模块功能
先清空.gitmodules
中的内容
再执行文件的删除
————
其他命令
1 | .gitmodules中子模块的内容更新到.git/config中 |
关闭issue
格式Fixes #45
,45是issue的ID,在相应的issue的链接地址就有。
可以关闭issue的关键字:
- close
- closes
- closed
- fix
- fixes
- fixed
- resolve
- resolves
- resolved
不同的仓库中关闭issue
格式close username/repository#issue_number
关闭多个issues
格式closes #34, closes #23, and closes example_user/example_repo#42
Fork&Pull Request
1 | 1、目标仓库A 页面 Fork |
git停留在writing objects
1 | git config --global http.postBuffer 524288000 |
http.postBuffer默认上限为1M,上面的命令是把git的配置里http.postBuffer的变量改大为500M
文件大,上传慢
1 | git remote set-url origin [你的ssh地址] |
把远程仓库的上传由原来的HTTPS改为SSH上传,github在国内本身就慢,还可能被dns污染 , 因此推荐使用SSH上传