《吐血整理》一篇文章教你学废Git版本管理(中)

简介: 一篇文章教你学废Git版本管理

5. 让Git不Tracked特定文件「.gitignore文件配置」


当我们使用git add命令把未标记的文件添加到缓存区后,Git就会开始跟踪这个文件。 对于一些比如:自动生成的文件日志临时编译文件应用签名文件等,就没必要进行跟踪了, 我们可以编写一个**「.gitignore文件」,把不需要跟踪的文件和文件夹写上,git就不会去 跟踪这些文件了,另外:.gitignore文件与.git文件夹在同级目录下**。

如果不想自己写这个文件,可以到 github.com/github/giti… 选择对应的模板,复制粘贴。 也可以自行编写,支持简化了的真这个表达式(规范与示例模板摘自:Git王者超神之路


  • * : 匹配零个或多个任意字符


  • [abc]:只匹配括号内中的任意一个字符


  • [0-9]:代表范围,匹配0-9之间的任何字符


  • ?:匹配任意一个字符


  • **:匹配任意的中间目录,例如a/*/z可以匹配:a/z,a/b/z,a/b/c/z等


模板示例


# 忽略所有以 .c结尾的文件
*.c
# 但是 stream.c 会被git追踪
!stream.c
# 只忽略当前文件夹下的TODO文件, 不包括其他文件夹下的TODO例如: subdir/TODO
/TODO
# 忽略所有在build文件夹下的文件
build/
# 忽略 doc/notes.txt, 但不包括多层下.txt例如: doc/server/arch.txt
doc/*.txt
# 忽略所有在doc目录下的.pdf文件
doc/**/*.pdf


有一点要特别注意!!!!


配置.gitignore只对那些没有添加到版本控制系统的文件生效(未Tracked的文件)!


举个简单的例子:


有A,B两个文件,你先把他两个add了,然后在.gitignore文件中 配置了不跟踪这两个文件,但是你会发现根本不会生效。


git add A
git add B
# 配置不跟踪A和B
git add .gitignore


所以,最好的做法就是在项目刚开始的时候,先添加.gitignore文件。 当然,即使是发生了,还是有解决方法的,可以键入下述命令清除标 记状态,然后先添加.gitignore,再添加文件即可:


git rm -r --cached .    # 清除版本控制标记,.代表所有文件,也可指定具体文件


另外,如果你用的IDEA系列的代码编辑器,可以安装一个「.ignore」的插件,手动 勾选不需要跟踪的文件,直接生成.gitignore文件。


6. 将暂存区的内容提交到本地仓库「git commit」


git commit -m "提交说明"    # 将暂存区内容提交到本地仓库
git commit -a -m "提交说明" # 跳过缓存区操作,直接把工作区内容提交到本地仓库


如果不加-m “提交说明”,git会让用你让默认编辑器(vi或vim)来编写提交说明。 除此之外,有时可能想修改上次提交的内容:提交说明,修改文件等:


# 合并暂存区和最近的一次commit,生成新的commit并替换掉老的。如果缓存区没内容,
# 利用amend可以修改上次commit的提交说明。
# 
# 注:因为amend后生成的commit是一个全新的commit,旧的会被删除,所以别在公共的
# commit上使用amend!切记!!!
git commit --amend 
git commit --amend --no-edit # 沿用上次commit的提交说明


7. 查看工作区与缓存区的状态「git status」


git status      # 查看工作区与暂存区的当前情况
git status -s   # 让结果以更简短的形式输出


8. 差异对比(内容变化)「git diff」


git diff                     # 工作区与缓存区的差异
git diff 分支名              # 工作区与某分支的差异,远程分支这样写:remotes/origin/分支名
git diff HEAD               # 工作区与HEAD指针指向的内容差异
git diff 提交id 文件路径     # 工作区某文件当前版本与历史版本的差异
git diff --stage           # 工作区文件与上次提交的差异(1.6 版本前用 --cached)
git diff 版本TAG           # 查看从某个版本后都改动内容
git diff 分支A 分支B       # 比较从分支A和分支B的差异(也支持比较两个TAG)
git diff 分支A...分支B    # 比较两分支在分开后各自的改动
# 注:如果只想统计哪些文件被改动,多少行被改动,可以添加--stat参数


9. 查看历史提交记录「git log」


git log                 # 查看所有commit记录(SHA-A校验和,作者名称,邮箱,提交时间,提交说明)
git log -p -次数                # 查看最近多少次的提交记录
git log --stat                  # 简略显示每次提交的内容更改
git log --name-only             # 仅显示已修改的文件清单
git log --name-status           # 显示新增,修改,删除的文件清单
git log --oneline               # 让提交记录以精简的一行输出
git log –graph –all --online    # 图形展示分支的合并历史
git log --author=作者           # 查询作者的提交记录(和grep同时使用要加一个--all--match参数)
git log --grep=过滤信息         # 列出提交信息中包含过滤信息的提交记录
git log -S查询内容              # 和--grep类似,S和查询内容间没有空格
git log fileName              # 查看某文件的修改记录,找背锅专用


除此之外,还可以通过 –pretty 对提交信息进行定制,比如:



更多规则与定制如下(更多可参见:Viewing the Commit History) format对应的常用占位符:(注:作者是指最后一次修改文件的人,提交者是提交该文件的人)


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


一些其他操作:


选项 说明
-p 按补丁格式显示每个更新之间的差异
–stat 显示每次更新的文件修改统计信息(行数)
–shortstat 只显示 –stat 中最后的行数修改添加移除统计
–name-only 仅在提交信息后显示已修改的文件清单
–name-status 显示新增、修改、删除的文件清单
–abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符
–relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)
–graph 显示 ASCII 图形表示的分支合并历史
–pretty 格式定制,可选选项有:oneline,short,full,Fullerton和format(后跟指定格式)


还有一些限制log输出的选项:


选项 说明
-(n) 仅显示最近的 n 条提交
–since, –after 仅显示指定时间之后的提交。
–until, –before 仅显示指定时间之前的提交。
–author 仅显示指定作者相关的提交。
–committer 仅显示指定提交者相关的提交。
–grep 仅显示含指定关键字的提交
-S 仅显示添加或移除了某个关键字的提交


10. 查看某个文件是谁改动的「git blame」


git blame 文件名 # 查看某文件的每一行内容的作者,最新commit和提交时间


这里为了演示,先修改一波作者用户名和邮箱,然后往1.txt中新增内容:



Tip:如果你用的IDEA系列的编译器,右键行号,选择Annotate也可以实现同样的效果。如:



11. 设置Git命令别名「git config –global alias」


在终端使用Git命令的时候,虽然可以通过按两次tab来自动补全。但是有些命令比较常用, 每次都要敲完就显得有些繁琐了,可以为这些命令起一个简单的别名,比如: status为st,checkout为co ; commit为ci ; branch为br等,设置示例如下:


git config --global alias.st status



别名的设置保存在git的配置文件中:



12. 为重要的提交打标签「git tag」


对于某些提交,我们可以为它打上Tag,表示这次提交很重要, 比如为一些正式发布大版本的 commit,打上TAG,当某个版本出问题了,通过TAG可以快速找到此次提交对应的Hash值, 直接切换到此次版本的代码去查找问题,比起一个个commit找省事多了。

Git中的标签分为两种:轻量级标签附加标签,命令如下:


git tag 标记内容                    # 轻量级标签
git tag -a 标记内容 -m "附加信息"    # 附加标签


如果想为之前某次commit打TAG,可以找出此次提交的Hash值,添加-a选项,示例如下:


git tag -a 标记内容 版本id      # 比如:git tag -a v1.1 bcfed96


另外,git push 的时候默认不会把标签推送到远程仓库,如果想把标签页推送到远程仓库,可以:


git push origin 标记内容    # 推送某标签到远程仓库
git push origin --tags     # 删除所有本地仓库中不存在的TAG


除此之外还有下述常规操作:


git checkout -b 分支名 标记内容          # 新建分支的时候打上TAG
git show 标记内容                       # 查看标签对应的信息
git tag -d 标记内容                     # 删除本地TAG
git push origin --delete tag 标记内容   # 删除远程TAG


Git文件恢复与版本回退


1. 文件恢复(未commit)「git checkout」


如果在工作区直接删除已经被Git Tracked的文件,暂存区中还会存在此文件:



Git告诉你,工作区的文件被删除了,你有两种可选操作:「删除缓存区文件」 或 「恢复被删文件」:


# 删除暂存区中的文件:
git rm 文件名
git commit -m "提交说明"
# 误删恢复文件(用暂存区的文件覆盖工作区的文件)
git checkout -- 文件名
# Tip:git rm 等价于 git rm --cached 文件名 + rm 文件名
# 务必注意:git checkout会抛弃当前工作区的更改!!!不可恢复!!!务必小心!!!


2. 文件恢复(已add未commit)「git reset HEAD」


如果更改已经add到暂存区中,想恢复原状,可以执行下述命令:


git reset HEAD 文件名   
git checkout 文件名


3. 版本回退(已commit)【git reset –hard】


文件已经commit,想恢复未上次commit的版本或者上上次,可以:


git reset HEAD^             # 恢复成上次提交的版本
git reset HEAD^^            # 恢复成上上次提交的版本,就是多个^,以此类推或用
git reset HEAD~3            # 也可以直接~次数
git reset --hard 版本号      # git log查看到的Hash值,取前七位即可,根据版本号回退


reset命令的作用其实就是:重置HEAD指针,让其指向另一个commit,而这个动作可能会对 缓存区造成影响,举个例子:


本来的分支线:- A - B - C (HEAD, master),git reset B后:- A - B (HEAD, master)解释:看不到C了,但是他还是存在的,可以通过git reset C版本号找回,前提是 C没有被Git当做垃圾处理掉(一般是30天)。


reset提供了三个可选参数


  • soft:只是改变HEAD指针指向,缓存区和工作区不变;


  • mixed:修改HEAD指针指向,暂存区内容丢失,工作区不变;


  • hard:修改HEAD指针指向,暂存区内容丢失,工作区恢复以前状态;


4. 查看输入过的指令记录「git reflog」


Git会记住你输入的每个Git指令,比如上面的git reset 切换成一个旧的commit,然后 git log后发现新提交的记录没了,想切换回新的那次commit, 可以先调git reflog 获取新commit的Hash值,然后git reset 回去。


git reflog



:指令记录不会永久保存!Git会定时清理用不到的对象!!!


5. 撤销某次提交「git revert」


有时可能我们想撤销某次提交所做的更改,可以使用revert命令


git revert HEAD             # 撤销最近的一个提交
git revert 提交的Hash值     # 撤销某次commit



注意!!!


不是真的把提交给撤销了,而是生成一个新的提交来覆盖旧的提交,被撤销的提交 和新的提交记录都会保存!!!如果不信的话,你可以再键入git revert HEAD, 会发现被撤销的更改又变回来了。简单点说:「撤销的只是文件变化,提交记录依旧存在」。


6. 查看某次提交的修改内容「git show」


git show 提交Hash值     # 查看某次commit的修改内容


7. 查看分支最新commit的Hash值「git rev-parse」


git rev-parse 分支名    # 查看分支最新commit的Hash值,也可以直接写HEAD


8. 找回丢失对象的最后一点希望「git fsck」


因为你的某次误操作导致commit丢失,如果git reflog都找不到,你可以使用git fsck,找到丢失 的对象的版本Hash值,然后恢复即可。


git fsck --lost-found



0x4、Git本地分支


1.分支的概念


分支并不是Git对象,和轻量级的TAG对象类似,只包含对commit对象的索引。只是分支更新后, 索引会替换为最新的commit,而TAG对象创建后索引就不在变化。分支文件保存与下述两个路径:


  • 本地分支当前项目/.git/refs/heads/


  • 远程分支当前项目/.git/refs/remotes/


说到分支,必然会提及HEAD,它指向「当前工作的本地分支」,对应文件:当前项目/.git/HEAD



下面通过示例和图解的方式帮大家理解分支:



如法炮制,提交两次:



从上面的图中不难发现这样的规律:每次commit,master都会向前移动,指向最新提交。 这个时候可能有些童鞋会问:commit之间的箭头哪来的或者说commit怎么串成一条线的


答:还记得一开始介绍的commit对象吗?里面有一个parent的值指向父commit的Hash值


2.创建其他分支的原因


通过两个常见的场景来体会创建其他分支的必要性:


场景一:


项目一般都是一步步迭代升级的,有大版本和小版本的更新: 大版本一般是改头换面的更新,比如 UI大改,架构大改,版本是: v2.0.0这样;小版本的更新一般是UI小改,Bug修复优化等,版本是: v2.0.11这样;只有一条master分支,意味着:你的分支线会 非常非常的长,假如你已经发布到了 第二个大版本,然后用户反馈第一个版本有很严重的BUG,这时候想切回第一个版本改BUG, 然后改完BUG切回第二个大版本,想想也是够呛的。 (PS:可能你说我可以对重要的commit打tag, 然后找到这个tag 切回去,当然也行这里是想告诉你引入其他分支会给你带来的便利)


场景二:


如果只有一个master分支的话,假如某次commit冲突了,而这个冲突很难解决或者解决不了, 那么整个开发就卡在这里,无法继续向后进行了。


3.一个简单的分支管理策略


为了解决只有一个master分支引起的问题,可以引入分支管理,最简单的一种策略如下:


master分支上开辟一个新的develop分支,然后我们根据功能或者业务,再在develop 分支上另外开辟其他分支,完成分支上的任务后,再将这个分支合并到develop分支上! 然后这个功能分支的任务也到此结束,可以删掉,而当发布正式版后,再把develop分支 合并到master分支上,并打上TAG。


master与develop分支都作为长期分支,而其他创建的分支作为临时性分支! 简述各个分支的划分:


  • master分支:可直接用于产品发布的代码,就是正式版的代码


  • develop分支:日常开发用的分支,团队中的人都在这个分支上进行开发


  • 临时性分支:根据特定目的开辟的分支,包括功能(feature)分支,或者预发布(release)分支, 又或者是修复bug (fixbug)分支,当完成目的后,把该分支合并到develop分支, 然后删除该分支,使得仓库中的常用分支始终只有:master和develop两个长期分支


4.分支创建与切换「git branch」


git branch 分支名    # 创建分支
git branch          # 查看本地分支


我们在master分支上创建一个develop分支,此时的版本线变成了这样:



此时虽然已经创建了develop分支,但是HEAD还是指向master,接着我们来切换分支:


git checkout 分支名         # 切换分支
git checkout -b 分支名      # 创建分支同时切换到这个分支



切换到develop后,提交一次,此时的版本线:



再提交一次,然后切换为master分支,此时的版本线:



切换回master后,提交一次,此时的版本线:



行吧,讲到这里,相信各位童鞋对Git中的分支已经有所了解了。


相关文章
|
6月前
|
网络安全 开发工具 git
版本管理 git 常用命令
版本管理 git 常用命令
49 1
|
6月前
|
缓存 开发工具 数据安全/隐私保护
通过一篇文章带你玩转git和GitHub
在现代软件开发中,版本控制系统是不可或缺的工具。Git和Github是其中最受欢迎的组合。Git是一个开源的分布式版本控制系统,用于追踪代码的改动,而Github则是一个基于Git的代码托管平台,提供了代码托管、协作开发等功能。
149 2
通过一篇文章带你玩转git和GitHub
|
存储 缓存 运维
【运维知识高级篇】一篇文章带你搞懂Git!(Git安装+全局配置+Git初始化代码仓库+Git四大区域+Git四种状态+Git常用命令+Git分支+Git测试代码回滚)
【运维知识高级篇】一篇文章带你搞懂Git!(Git安装+全局配置+Git初始化代码仓库+Git四大区域+Git四种状态+Git常用命令+Git分支+Git测试代码回滚)
256 0
|
6月前
|
Linux Shell 开发工具
一篇文章带你快速入门使用Git
一篇文章带你快速入门使用Git
|
Cloud Native Go 开发工具
开源项目的版本管理:Git的最佳实践
开源项目的版本管理:Git的最佳实践
205 0
|
安全 程序员 开发工具
代码版本管理笔记 | Python 程序员也应该会的 Git 分支操作
代码版本管理笔记 | Python 程序员也应该会的 Git 分支操作
188 0
|
数据采集 安全 JavaScript
代码版本管理笔记 | Python 程序员也应该会的 Git 进阶操作
代码版本管理笔记 | Python 程序员也应该会的 Git 进阶操作
169 0
|
数据采集 缓存 安全
代码版本管理笔记 | Python 程序员也应该会的 Git 基础操作
代码版本管理笔记 | Python 程序员也应该会的 Git 基础操作
|
存储 Linux 开发工具
学会使用Git,看这一篇文章就够了
以上是 Git 的简介绍和常用命令说明。希望这篇文章能够帮助初学者更好地理解和掌握 Git 的使用。Git 在代码管理中是一个非常重要的工具,尤其是在多人协作的情况下。因此,掌握好这些基本命令是非常有必要的。
|
存储 缓存 Shell
一篇文章搞懂Git与Github
一篇文章搞懂Git与Github