前言##
Git是一款免费、开源的分布式版本控制系统。使用Git可以方便的实现代码版本管理。
平时使用git的时候,也是遇到很多问题,但是每次解决完问题 之后就忘了解决方法,这里特意梳理一下。
实践##
首先,要明白Git不同于SVN(如果你曾使用过的话)。是一种完全不同的设计理念。
下图是git本地操作的简单原理图(图片来自网络搜索)。
其次,要明白图中绿色、黄色、蓝色三个部分所代表的含义。
基础###
我们首先创建一个目录(上图中绿色的work directory)
mkdir mywork
cd mywork
git status **查看当前git 仓库状态 **
不清楚当前git 仓库是什么状态时,可以使用这个命令,是一个常用的命令。
git init 初始化一个git 仓库
这样就创建了上图中蓝色的git repository
为了方便测试,我们在mywork 目录下创建一个readme.txt 文件,其内容为
git add readme.txt 添加文件到中转区(就是上图中黄色区域),也可以称为暂存区。
这样就相当于上图中操作1
如果add 到中转区的内容不想要了,也可以删除,这个很重要,后面还会说到。
git rm --cached
如果add 内容没问题,就可以提交了。
git commit -m "Version 1.0" 提交文件到本地仓库,并附带提交信息,这点和SVN倒是相似
相当于图中的操作2
git log 查看提交信息
我们可以看一下现在的提交信息:
这样,就完成了一次提交。注意这里的commit和SVN中的commit的意义是不同的。
Branch 分支###
git branch 查看当前所处分支
*master 一般情况下,都会在master分支上。
git branch test 创建test 分支
git checkout test 切换到test 分支
Switched to branch 'test'
我们在test 分支对readme.txt 文件做一些修改:
echo 这是在test分支的修改 >> readme.txt
然后将其提交到test branch
git commit -am "test branch commit"
这里由于没有新增文件,这样合并的操作可以一次完成add和commit。如果有新增文件,还是需要单独 add 的。
git log 查看commit 信息
可以查看到当前分支test上目前为止所有的commit 信息。
我们在切换回master分支
git checkout master
这个时候,如果我们用git log 查看一下可以发现,master分支并没有我们在test分支上的提交信息。同时readme.txt 这个文件的内容,也实没有改变。
所以,我们现在需要将test分支的内容合并到master分支上
git merge test
Updating 1f812af..dd7773e
Fast-forward
readme.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
这个时候,我们再执行git log 就可以看到test 分支上提交的信息了,同时readme.txt 的内容也变成了修改后合并的内容。
现在test如果不再需要其他的开发内容,我们就可以将它删除了
git branch -d test
Deleted branch test (was dd7773e).
提交到远程仓库###
到目前为止,所有的操作都是在本地完成,即便是完成了commit(这个可和Svn的Commit不是一回事)
实际开发中,还需要将commit 之后的内容提交到远程仓库中。
可以在自己的Github 上创建一个git仓库 : https://github.com/USERNAME/GitStudy.git
由于我们已经在本地创建了git仓库,所以现在要做的就是把本地仓库和远程仓库(GitStudy)关联起来。
git remote add origin https://github.com/USERNAME/GitStudy.git
如果你是第一次使用git ,这里可能还需要如下配置
git config --global user.name "Your Name"
git config --global user.email you@email.com
这样,我们本地仓库就和远程仓库关联了,首先,我从需要从远程从库把最新的代码pull下来
可以看到,这里已经从github把内容更新到了本地。接下,就是最后一步,把我们修改过的内容,提交的远程仓库。这个时候,可以用git status 查看一下本地仓库状态,如果没有需要提交的内容,就可以直接push 了。
这时候 ,我们可以在github看到我们提交的内容了。
解决冲突###
上面的流程,是日常使用git当中最完美的一种,整个过程没有冲突。但是实际开发中,冲突是不可避免的。下面来说一下冲突产生的原因及如何解决。
假设现在有这样一个需求,需要在readme.txt 中添加自己的邮箱地址。
同时现在有两个程序员CoderA和CoderB,他们分别以自己的名字创建了分支,并修改了readme.txt。
好了,现在切换到master分支开始合并这两个分支的内容:
结果在merge CoderB 分支的时候发生了冲突。这个完全是由于两个分支同时修改同一个文件造成的。
我们打开 readme.txt 文件,看看它的内容:
这是一个测试文本1.0
这是在test分支的修改
<<<<<<< HEAD
"CoderA@163.com"
=======
"CoderB@163.com"
>>>>>>> CoderB
现在对冲突就行修改,将readme.txt 内容修改如下
这是一个测试文本1.0
这是在test分支的修改
"CoderA@163.com"
"CoderB@163.com"
然后再次提交并push到远程仓库。
git commit -am "conflict reslove"
git push origin master
这样,就完成了一次简单的冲突解决。日常开发中,要尽量避免这种同时修改同一文件的问题。同时,也要养成每天在修改代码之前update的习惯。
后悔药###
有时候commit之后发现,commit的内容有些问题,想回退到之前的某个点。这个时候就可以使用git reset 命令
根据–soft –mixed –hard,会对working tree和index和HEAD进行重置
git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息
git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可
git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容
我们首先看一下当前的commit信息:
现在,如果决定回退到id 位4561f5d65a7ec7d6fc6a411046172509f66761d8 的commit状态。也就是 Merge branch 'master' 的那个节点。
git reset --hard 4561f5d65a7ec7d6fc6a411046172509f66761d8
现在在看readme.txt 发现他已经回退到之前的状态了。因为我们使用了最强大的 --hard。
而且由于我们之前已经将之前的commit 内容提交到了远程仓库(github),所以github提交的内容,也需要强制进行回退。
git push origin HEAD --force
现在我们到github 上会发现,代码已经回退到之前的版本了。
好了,这样就完成了一次代码回退。可以发现,--hard 和 --force 将导致代码内容从本质内容上物理回退。所以,一定要谨慎使用。最好还是使用默认的方式,除非十分确定要回退源码。
.gitignore
使用Git的过程中,一般都会接触到.gitignore 这个文件。顾名思义,这个.gitignore 的作用就是帮助我们忽视一些不必提交的文件,比如编译之后产生的.class 文件,一些本地化的配置文件等。一般来说,IDE 会自动帮我们生成一个这样的文件,配置的内容要不用过多考虑。
但是,我们在使用过程中有时候会发现,这个.gitigore 失效了。我们在commit的过程中,依然会有不需提交的内容出现在提交列表中。这里需要明白,.gitignore 生效的范围是在由 working directory add 到 暂存区的过程中。也就是说,如果在生成.gitignore 之前进行了add 操作,那么.gitignore 将失效。那该如何解决这个问题呢?其实,也很简单,之前我们说过,add 到暂存区的内容,可以删除。因此,我们可以这样
git rm -r -f --cached .
这样我们就强制删除了暂存区(第一幅图中黄色区域)中所有内容,注意,--cached 后面有个点,代表所有文件。
这时候,我们再次git add . 然后commit,就会发现.gitignore 生效了。
后话##
很多人接触的第一款版本控制系统并不是Git,而是SVN。个人感觉,二者各有千秋,无所谓那个更好。Git相较于SVN固然强大,但也因为其过于强大,产生问题是会有些复杂,不好解决。所以,SVN如果够用,完全是一个好的选择。
这里简单列举了日常开发中使用过的git命令,及遇到问题的解决方法。截图的时候,使用的电脑不是个人账户,所以就打了马赛克。