这两天在学习netty的时候顺便完成了一个小demo,在实现这个demo的过程中,发现了代码版本管理的重要性,因此今天下午认真学习了Git,并写这个博客来记录一下。
首先说,Git是什么?Git是目前世界上最先进的分布式版本控制系统,通过Git,我们可以轻松地回滚到我们需要的任一历史版本;同时在团队协作时,我们能够更容易地进行代码同步等操作。接下来我以demo这个项目为例,展示一下Git的常见操作。
在项目开始前或者项目进行中都可以进行Git仓库的创建,首先进入项目的根目录,然后运行
git init
之后,在根目录下就会出现一个.git文件夹(该目录默认是隐藏的),这样我们的本地Git仓库就建好了,但是现在这只是一个空仓库,我们的文件还没有放入这个仓库。
git add readme.md
git add src/
git commit -m "add readme and src/"
使用以上命令,可以把文件添加到版本库,该命令既可以用来添加单个文件,也可以用来添加文件夹。
注意一下,我们执行完git add命令后,必须得执行git commit命令,因为git add只是把文件添加到暂存区(stage),而git commit命令是把暂存区的文件提交到当前分支,“”里面是和该提交有关的描述信息,自己可以根据实际情况进行描述。如下图所示。因此,这两个命令必须都得执行。
工作区就是我们项目的根目录,而版本库则位于.git文件夹内。我们通过add命令将修改的文件由工作区转移到暂存区(stage),然后通过commit命令把暂存区的内容提交到当前分支master。
如果我们想把项目代码回退到上一个版本,或者回退到指定版本,应该用什么命令呢?
在Git中,用Head来表示当前版本,如果想要回退到上个版本,只需
git reset --hard HEAD^
如果想回退到上上个版本呢?使用git reset --hard HEAD^^,如果想要回退到上上…个版本,只需要使用git reset --hard HEAD~N,N是想要回退的版本个数。
git reset --hard HEAD~20
即回退到往前20个版本。如果我们想要回退到指定版本呢?那我们就需要知道想要回退到的版本号,通过
git log
可以查看历史版本号,如下所示,然后选择我们需要的那个版本号。
$ git log
commit c317ac6fe8af7fbe084d5a4689e22f128aef9c9c (HEAD -> master)
Author: Lu <10568269+luxinfeng@users.noreply.github.com>
Date: Wed May 20 15:21:36 2020 +0800
third version
commit 44a64dec50dc511480615745aee0c0f27660127a
Author: Lu <10568269+luxinfeng@users.noreply.github.com>
Date: Wed May 20 15:21:15 2020 +0800
second version
commit 6520506073bfaf16ead102433c6109a9dc66643b
Author: Lu <10568269+luxinfeng@users.noreply.github.com>
Date: Wed May 20 15:21:02 2020 +0800
first version
其中,comiit后面就是版本号,我们可以通过
git reset --hard 44a64dec50dc511480615745aee0c0f27660127a
将项目回退到第二个版本,如果版本数较少,我们可以只输入版本号的前几位,Git会自动寻找对应的版本号,如果版本数较多,可以会引起冲突,我们现在的版本数较少,我们执行如下代码
git reset --hard 44a6
也可以回退到第二个版本。
现在我们回到第二个版本了,但是如果我们想要再回到第三个版本怎么办?使用git log查看版本号?
$ git log
commit 44a64dec50dc511480615745aee0c0f27660127a (HEAD -> master)
Author: Lu <10568269+luxinfeng@users.noreply.github.com>
Date: Wed May 20 15:21:15 2020 +0800
second version
commit 6520506073bfaf16ead102433c6109a9dc66643b
Author: Lu <10568269+luxinfeng@users.noreply.github.com>
Date: Wed May 20 15:21:02 2020 +0800
first version
commit d33955c2800f7f12811e30a597200da69795363c
Author: Lu <10568269+luxinfeng@users.noreply.github.com>
Date: Wed May 20 15:20:17 2020 +0800
first version
发现找不到第三个版本号,这时我们可以使用git reflog命令,该命令记录了你的所有操作,执行该命令。
$ git reflog
44a64de (HEAD -> master) HEAD@{0}: reset: moving to 44a64dec
c317ac6 HEAD@{1}: commit: third version
44a64de (HEAD -> master) HEAD@{2}: commit: second version
6520506 HEAD@{3}: commit: first version
d33955c HEAD@{4}: commit: first version
57f0388 HEAD@{5}: commit (initial): first version
可以看到我们第三个版本号的前几位是c317ac6,查到了版本号,我们就可以继续用git reset --hard c317ac6来回退到第三个版本了。
如果我们在写代码的过程中,发现某些文件的修改出问题了,想要取消这些修改,该怎么办呢?版本回退?使用版本回退确实可以撤销修改,但是有可能回退的太多,许多工作还得重新做,挺浪费时间和精力的。这时,我们可以使用git checkout – 要撤销修改的文件 来进行操作。比如我们想要撤回对readme.md文件的修改,只需要执行
git checkout -- readme.md
这样,就会把readme.md文件恢复到最近一次执行git commit或者git add后的状态。也就是说,git checkout – readme.md命令只会撤销在工作区(可以看文章一开始的那张图)的修改,如果你想撤销的修改已经被git add命令添加到暂存区或者git commit命令提交到当前分支的话,使用git checkout是没法回退的。如果想要撤销暂存区的修改,可以使用
git reset HEAD readmd.md
该命令可以把暂存区的内容回退到工作区。如果想要撤回已经提交到当前分支的修改,那就可以使用版本回退的命令,回退到自己需要的版本。
在Git中,删除也是一种修改操作,也就是说,如果我们想要找回被删除的文件,可以使用上述撤销修改的操作。比如,我们现在想要删除test.md文件,则可以使用
git rm test.md
git commit -m "del test.md"
执行以上操作,即可删除test.md文件。如果我们在本地使用文件资源管理器删除掉test.md文件后想找回该文件,只需要执行
git checkout -- test.md
如果我们在执行完git rm test.md后,想找回该该文件,只需要执行
git reset HEAD test.md
如果我们执行 commit后想找回该文件,只需要
git reset --hard HEAD^
回退到上一个版本即可。
如果我们需要把项目进行备份或者需要多人协作时,我们一般会把项目上传到GitHub进行远程同步。
首先,登录GitHub,然后创建一个新的Repository,假定这个新建的Repository的名称为GitTest。在把本地的这个GitTest仓库推送到GitHub前,我们需要先把自己本地的SSH Key添加到自己的GitHub上。使用
ssh-keygen -t rsa
可以在本地生成公钥和私钥,这个公钥和私钥一般存放在C:\Users\name.ssh文件夹下,打开那个后缀是pub的公钥,将该文件中的内容添加到GitHub中的ssh keys中即可。
然后,执行
git remote add origin git@github.com:luxinfeng/GitTest.git
上述命令中的origin是远程库的名称,这个自己可以更改,github.com:后面是你新建的Repository在GitHub上的位置,需要根据你自己的情况进行更改。这样,我们就成功的关联了本地库与远程库。然后执行
git push -u origin master
就可以把本地当前分支(master分支)的所有内容推送到远程库了。需要注意的是,如果你在GitHub创建新的Repository时,选择了初始化md文件,这样远程库就不是空的了。在执行上述git push 命令的时候会报错,我们需要先执行以下命令
git pull origin master --allow-unrelated-histories
将远程库中的文件拉到本地库,–allow-unrelated-histories参数的作用是允许合并不相干的历史记录。
然后再执行git push命令就可以了。
第一次执行git push时,需要使用-u参数,作用是推送当前master分支的所有内容,以后再推送的话,只需执行
git push origin master
推送最新修改即可。
创建分支的命令
git branch dev
切换分支的命令如下
git switch dev
创建并切换分支可以用如下命令
git switch -c dev
切换后,我们的当前分支就是dev分支了,dev分支上的修改,在merge之前,其它分支是不知道的。我们用图来展示一下该过程
在创建分支之前,只有一个主分支master,HEAD指向当前分支的当前版本节点
我们在master分支上不断执行commit命令,该master分支也会不断地变长。HEAD始终指向当前提交节点。当我们创建并切换到一个新的dev分支后,如下图所示。
当前分支变为dev,HEAD指向了dev分支。当我们在修改当前分支的时候,dev分支向前移动,而master分支不变。
我们把当前分支切换回master,然后执行合并命令,将dev分支合并到master
git merge dev
合并的过程,就是将master指针指向dev指针所指的位置,因此合并过程非常迅速。
合并完成后,如果不再需要dev分支了,我们可以使用以下命令删除dev分支。删除前,使用git branch可以查看当前分支和所有分支(*所指的就是当前分支)。
$ git branch
dev
* master
然后执行删除操作
$ git branch -d dev
Deleted branch dev (was e83095d).
再查看所有分支
$ git branch
* master
只剩下master分支了,dev分支已经被删除了。注意,当我们在合并分支的时候,可能会出现以下情况
$ git merge dev
Auto-merging readme.md
CONFLICT (content): Merge conflict in readme.md
Automatic merge failed; fix conflicts and then commit the result.
提示我们在合并的过程中存在冲突。这时候我们可以查看冲突的文件,此案例中的冲突文件为readme.md,打开此文件,内容如下
This is the second version.
<<<<<<< HEAD
This is a master error.
=======
This is a merge error!
>>>>>>> dev
Git用<<<<<<<、=======、>>>>>>>来区分不同。<<<<<<< HEAD指的是当前分支的内容是“This is a master error.”,而>>>>>>> dev代表dev分支中此处的内容是“This is a merge error!”
我们需要手动修改这个冲突,比如,我们可以切换到dev分支,然后把“This is a merge error!”改为master中的“This is a master error.”,这样就可以正常的合并了。
使用上述合并操作不会再log中留下合并记录,如果想在日志中留下合并记录,需要使用以下命令。
git merge --no-ff -m "merge with no-ff" dev
有时我们当前分支的任务还没有做完,但是需要立刻去别的分支上完成一些工作,本分支的任务没有完成,也没法提交,如何保存当前的工作现场呢?我们可以使用如下命令
git stash
保存现场后,我们就可以切换到别的分支去完成任务,等工作完成后,再切换回本分支,然后执行
git stash apply
或者
git stash pop
命令来恢复工作现场。保存的工作现场可以使用git stash list命令查看。以上两个命令的区别是apply命令再恢复后不会删除之前保存的工作现场,可以使用git stash push来删除;而pop命令再恢复的同时会删除掉stash内保存的工作现场。
我们前面讲过用`
git push origin master
来推送master分支,如果我们想推送其它分支呢?只需改动最后的参数,如果想推送dev分支,就执行
git push origin dev
即可。
以上就是自己的Git笔记,后期可能还会继续更新。