git架构图解
最近又遇到Git了,发现网络上Git的资料确实不咋滴,难懂不全面。没法,自己来整理整理吧。至于Git是什么我就不多说了,相比svn上手确实更难。与svn集中版本库相比较,Git被称作分布式版本库,在分布式的版本库中任何一个库都可以作为中心库看待。如果说svn是颗树,那么Git就像一张网。Svn在每个目录都有一个.svn文件夹存放信息,而git只在根目录才有,这就决定了svn可以单独拉取某个子目录或者某个文件,而git需要全部拉取。传言高版本git可以,反正我没成功。
废话不多说,先上一张图(在此称赞一下 亿图图示专家,尝试了n多软件,连一直在用的xmind也无法表达我的思维。这软件还是国产的哦,简洁美观,顶一下)
图比较大,如果看不清楚请下载我 资源,原创的收1分,望理解~~!
下面开始对图详解,假设你是图中的开发者1,红线代表你可以操作的,流程中的虚线代表可以有,但是往往不用的。讲解的顺序图中红圈已经标明。
1:git --bare init
--bare代表只存储变化不存储实际文件,作为中心服务器一般都是这样初始化的。初始化后会默认创建一个master分支(怎么创建其他分支参考下面的git push)。这里一个有趣的问题来了,不是说git是分布式的么,任何一个库都是中心库,那么为何还有中心服务器?中心服务器有什么不同?弄一个中心服务器的好处就不多说了,简单解释下中心服务器的不同之处。我们init一个git库后,要想其他人能访问,必须得共享出去。共享的方式有好多种,需要依赖其他软件如gitosis等。具体请查阅 这篇文章。这样别人就能通过clone、pull、push、fetch命令跟你打交道了。如果开发者2也安装了发布工具,那么同一个项目你可以跟两个远端库交互。这种情况很少遇到,一般都是大家通过中心服务器来间接交互。
2-1:git clone [-b branchName] url
首次参与项目需要先clone下来,-b参数可以指定分支名,不指定默认使用master分支。
这时候你本地会有一个项目的拷贝。这时候你可以查看一些信息:
1)git remote show 查看所有远程库,你会发现输出origin,origin就代表你刚才clone下来的远程库。如果开发者2安装了发布软件,你可以使用“git remote add dota 开发者2url”来添加一个远程库且你把他命名为dota,这样你这个项目就可以跟两个远程库打交道了。对应的还有git remote rm dota,git remote rename dota dota2,git remote set-url dota url2。
2)git remote show origin 查看远程库origin的详细信息。
3)git branch [-r -a] 查看分支,不带参数是查看本地分支,-r查看远程的,-a查看所有。其中前面带*号的代表你当前工作目录所处的分支,remotes代表远程库,remotes\origin代表远程库中的origin,remotes\origin\master代表远程库中的origin中的master分支。HEAD那个不懂干嘛
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
2-2:git pull origin branch1
从远端origin拉取branch1分支的内容然后合并到当前所处的本地分支。直接git pull的话默认远程库是orgin,默认远程库的分支是master。
2-3:git fetch origin branch1或者git fetch origin branch1:tmp
从远端origin拉取branch1分支的内容到本地origin/branch1分支里面,如果本地没有这个分支就创建。更清晰点的应该使用git fetch origin branch1:tmp直接指明本地分支用tmp这个名字。直接git fetch是什么效果还没试过。由此可见git fetch和git pull都是从远程拉取分支到本地,不同的是git pull拉取后马上自动合并。
3:git push origin master:branch1
把本地的master分支提交到远程origin的branch1分支上,如果远程没有branch1分支,则创建,所以远程分支的创建方法应该如此。对应的远程分支的删除则是git push origin :branch1,命令中本地分支名留空则能删除远程branch1分支了。值得指出的是,远端分支不需要指明全称,例如你git branch -a看到有一个remotes/origin/dir1/branch1那么你只需要写上dir1/branch1即可。下面来最讨厌的默认情况。
git push origin master(本地master到远程master)
git push(哥不干了)
4:git branch -b branchnew branchold
这个是本地分支的创建方法之一(另一种方法参考git checkout),以branchold为模板,创建branchnew分支,这个branchold既可以是本地的也可以是远端的,如果是远端分支的记得输入全名,例如remotes/origin/master。如果没用指明branchold,则默认使用HEAD所指向的提交创建分支。
本地分支的删除使用git branch -d branchname。如果该分支有改动且没有合并到其他分支上,会报错。你可以使用-D强行干掉。
5:git checkout -b branchnew branchold
该命令的本意是切换本地分支,可以使用最简单语法git checkout branchname,如果分支不存在则报错。而git checkout -b branchnew branchold是branchnew存在则切换,不存在则以branchold为模版创建一个新分支,然后切换到新分支上。这是创建本地分支的第二个方法。
6:其实6可以当不存在,如图如果你是开发者1,那么工作目录就是branchA,你用pull、fetch以及即将介绍的merge处理分支的时候,如果branchA被更新了,那么就相当于你的工作目录被更新了。分开是为了下面的介绍。
7:git merge branch1 branch2 branch3......
把branch1、branch2、branch3等合并到当前分支。当然,实际中当然是一个一个来了,要不处理冲突可能会吓死你。
8和9:git add、git rm和git commit
到了这里,需要解释下图中黄色底的那些文字的概念了。
如果你在branchA上工作,其实branchA还可以细分为三块。
work tree:你当前在修改的项目,你能看到的文件。
index file:当你使用git add file1 file2......系统会在索引文件中记录你打算提交的东西(新添的文件和修改的文件都使用git add,别纠结这个了,删除的文件使用git rm)。
commit:真正的branchA分支体。使用git commit -m “msg”可以提交索引文件中记录的提交内容。如果你之前没有使用git add或者git rm把文件修改标记到索引文件中,则提交失败或者提交不全。有一种情况例外,-a参数可以直接提交所有被git管理的文件,不需要使用git add添加到索引文件。至于-m则是必须的。
10:git tag tagname
标签是什么?其实没那么复杂,跟分支不是一个概念的。只是相当于你在当前分支的当前版本用一些字符标记一下,一般标签内容都是项目版本号。开发到一定程度标记一下,代表到此为止版本1.0.1完成了出来了。
本地标签的创建 git tag tagname或者git tag -a v1.1.1 -m ‘my v1.1.1’
本地标签的删除 git tag -d tagname
本地标签的查看 git tag -l ‘1.4.2*’
使用git push的时候默认是不提交标签的,所以当你打了标签要使用git push origin -tags来单独提交标签。某个版本打标签要在commit之后。上述创建标签的-a参数一定要加上-m输入描述。或者直接-s替代-a不需要-m,描述自动帮你加上。
远程标签删除使用 git push origin :refs/tags/0.1.3
标签详细查看使用 git show v1.1.1
11:git diff
这玩意太博大精深了,不做详解,列出常用的。
master分支的某个版本号某个文件与当前该文件比较:
git diff 0c5ee16a6a4c849d0ae0448caa8ff174399c7c3c ./socket_helper.cpp
两个tag(项目版本)之间相差哪些文件,做补丁包常用:
git diff tag1 tag2 --staged
太多了,我研究不过来,改天吧。
待写问题:冲突识别和解决