Git学步

in DevOps with 0 comment

Git 是一款开源的分布式版本控制系统,是Linux之父Linus开发的版本控制软件,为帮助管理Linux内核开发而诞生,这期间有故事,当然,这不是我记录文章的重点,我只是感慨:牛逼!

这里只是记录Git学习的常用命令,话说20%的命令可以涵盖80%的场景,二八定律套一套,就可少学一套!这里不会记录Git的安装,也不会记载与SVN等其他版本控制系统的区别,只是学一学别人的步伐,具体深究详情可参考链接。

创建版本库

初始化本地仓库,当前目录下多了一个.git的目录

git init

将新建文件加入到Index暂存区

git add testgitaddfile.txt

将暂存区提交到当前分支版本库,创建Git版本库时,Git自动为我们创建了唯一一个master分支

git commit -m "add file"

提交流程可以由下面简图标识:

git_add_commit_flow

推送到远程关联的主分支

git push -u origin master

这里我已经绑定了自己安装的Gitlab,同步到Gitlab服务器

git_push_gitlab

登录Gitlab查看,查看确实提交上去了

git_push_gitlab_detail

状态与比较

修改testgitaddfile.txt文件内容后,查看状态,如看文件是否修改过

git status

git_status_add_and_commit

上图结果输出,可知,testgitaddfile.txt被修改过了,但还没有准备提交的修改。

我们可以进行文件比较,查看修改内容

git diff testgitaddfile.txt

git_diff_imissyouverymuch

可以看出距离上次文件修改添加了内容"I miss you very much!"

再次添加文件到暂存区git add testgitaddfile.txt后,查看状态,变成未提交:

git_status_add_not_committed

再次git commit testgitaddfile.txt后,状态变成没有未提交的文件,工作区是干净的:

git_status_add_and_commit

git diff 是只比较比较工作区和暂存区(最后一次add)的区别,git diff --cached 是只比较暂存区和版本库的区别,git diff HEAD -- filename 是只比较工作区和版本库(最后一次commit)的区别。

修改工作区testgitaddfile.txt文件内容后,再次比较:

git_diff_head_cached

暂存区和版本库当前分支比较没有变化,工作区和暂存区、工作区和版本库当前分支比较都发生变化了。

git add 文件,提交到暂存区后,继续比较:

git_diff_after_add

工作区和暂存区比较没有变化,版本库当前分支和暂存区、工作区和版本库当前分支比较都发生变化了。

回退与撤销

我们可以先查看提交的版本历史记录,--pretty=oneline 进行单行输出,比较方便

git log --pretty=oneline

git-log

commit id版本号计算出一串十六进制数字。

HEAD表示当前版本 上一个版本就是HEAD^ 上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

回退上一个版本,这样历史就可以重写了

git reset --hard HEAD^

git-reset

历史是可以重写 了,但是难免后悔,总想回到最后发生的剧本,蓦然回首才发现,最初注定的结局才是最香的。查看命令历史,并回到最新版本

git relog
git reset --hard ff9e036

git_relog

人无完人,犯错总是难免的,工作区内容改错了,就原谅你,权当没有发生。我们需要撤销修改,回到最后一次add状态,直接丢弃工作区的修改

git checkout -- testgitaddfile.txt

没有--,就变成了"切换到另一个分支"的命令,撤销工作区修改注意加上--

git_checkout__

git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本

当你不仅改乱了工作区文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>,回退暂存区,第二步操作git checkout -- <file>回退工作区。

git_reset_head

已经提交了不合适的修改到版本库时,直接版本回退,体验不同的平行空间吧

删除文件

当某些不和适宜的文件需要丢弃时,就需要删除,也要提交到版本库

rm <file>命令删掉文件后,查看文件状态

image.png

文件处于删除状态,需要把版本库的文件也删了

git rm test.txt
git commit -m "remove test.txt"

git_rm_deleted

在Git世界了后悔药总是可以吃的,可以恢复版本库中被删除的文件

git checkout -- test.txt

我们只能恢复到文件的最新版本,你会丢失最近一次提交后修改的内容

远程仓库

我们可以在码云gitee创建新的仓库,如testproject

gitee_testproject

对于如何在gitee或github上创建账号,生成ssh key并把公钥key放至对应的账号配置中就自行参考了,关联远程仓库并推送

git remote add gitee git@gitee.com:wenqygitee/testproject.git
git push -u gitee master

-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,把本地的master分支和远程的master分支关联起来

git_remote_add-gitee

登录Gitee查看,发现推送成功啦

git_push_gitee

查看远程库地址

git remote -v

取消远程库关联

git remote rm origin

关联多个远程库时,可以未不同的远程库关联不同的名,也可以取消关联,重新绑定。

克隆远程库

克隆自建Gitlab的仓库项目

git clone git@xx.xxx.xxx.xxx:root/testproject.git

分支管理

创建并切换分支,-b参数表示创建并切换

git checkout -b dev

相当于两条命令

git branch dev
git checkout dev

列出所有分支,当前分支前面会标一个*

git branch

git_checkout_b_dev

git merge dev 指定分支合并到当前分支

git merge --no-ff -m "merge with no-ff" dev

默认Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息,--no-ff参数,表示禁用Fast forward模式,git log分支历史上就可以看出合并的分支信息

image.png

删除分支

git branch -d dev

git_branch_d_dev

新版本还可以用switch切换分支

git switch -c dev

多人协作,对同一份内容同时修改,多分支合并等,难免会发生冲突:

git_merge_conflict

Git用<<<<<<<=======>>>>>>>标记出冲突文件里不同分支的内容,修改冲突的文件内容后,再次提交,解决冲突

可以用git log查看分支合并情况

git log --graph --pretty=oneline --abbrev-commit

git_log_graph

Bug分支

通常手工工作进行中时,会插入紧急bug任务需要修复,这时可以先保存开发现场,创建修复分支修复bug,然后在切回开发分支,保存dev分支修改,切换master分支后,创建issue分支,并在issue分支上进行bug修复,并合并到master分支

先在dev分支上保存现场

git stash

切换master分支后,创建issue分支

git checkout master
git checkout -b issue

修复bug后,切回master分支,并将issue分支合并到master分支

git checkout master
git merge --no-ff -m "merged bug fixed" issue

git_merge_issue

合并完后,切换回dev分支,恢复之前进行到一半的现场,可以继续开发啦

git stash list
git stash pop

git_stash_pop

dev分支是早期从master分支分出来的,这个bug在dev分支上也可能存在。我们可以快速复制一个特定的提交到当前分支来修复bug,复制指定commit id的修改

git cherry-pick a82f58c

操作时,由于dev分支修改的是同一份内容,发生冲突了,修改内容后重新提交

git_cherry-pick

通常开发新特性,新功能,我们可以新建feature分支上开发

有时候分支还没合并就需要删除,提示删除不了,这时需要强制删除分支,-D 强制删除

git branch -D feature-one

推送分支

git push gitee dev

推送失败时可能你的小伙伴的最新提交和你试图推送的提交有冲突,可以先git pull 抓取最新分支,解决冲突,

git pull也失败了,原因是没有指定本地dev分支与远程gitee/dev分支的链接,关联链接

git branch --set-upstream-to=gitee/dev dev

git_branch_set_upstream

标签管理

发布一个版本时,我们通常先在版本库中打一个标签(tag),标签也是版本库的一个快照。

git tag <name>就可以打一个新标签

git tag v1.0.0

查看所有标签

git tag

默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,可以先找到历史提交的commit id,然后打上就可以

git tag v0.0.9 42dee2a

查看标签信息

git show v1.0.0

git_tag

删除标签

git tag -d v0.0.9

推送标签到远程

git push gitee v1.0.0

推送所有标签到远程

git push origin --tags

删除远程标签,本地也需先删

git tag -d v1.0.0
git push gitee :refs/tags/v1.0.0

查看远程分支

git ls-remote

git_tag_d

忽略文件

忽略某些文件,不需要加入到版本控制时,需要编写.gitignore文件,.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!

gitignore

可以查看别人整理的gitignore文件:https://github.com/github/gitignore

配置别名

对于git命令,有些难记的,可以偷懒取巧,取个别名

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.last 'log -1'
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

git_alias

配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用

每个仓库的Git配置文件都放在.git/config文件中

gitconfig

我们学习了常用的Git命令,知道了查看状态和比较,版本的回退和撤销,关联远程库,对分支和标签进行管理,还编写了忽略版本的文件,配置命令别名等等。Git学习,需要深究可以查看官网手册。

参考

https://git-scm.com/docs 官方文档
https://www.liaoxuefeng.com/wiki/896043488029600 廖雪峰Git教程
https://www.runoob.com/git/git-tutorial.html 菜鸟教程
https://time.geekbang.org/course/intro/100021601 玩转Git三剑客(付费视频教程)
https://learngitbranching.js.org/ Git教学网
https://backlog.com/git-tutorial/cn/ 猴子都能懂的GIT入门