1 从服务器上克隆完整的Git仓库(包括代码和版本信息)到本机上。2 在自己的机器上根据不同的开发目的,创建分支,修改代码。3 在单机上自己创建的分支上提交代码、合并分支,提交到本地版本库。4 把服务器上最新版的代码pull/fetch下来,解决服务器版本库与本地代码的冲突,然后跟自己的主分支合并。5 如果没问题,push到服务器
如果中央服务器故障,Git本地仓库包含代码库还有历史库,不需要网络,自己可以在脱机环境查看开发的版本历史,在本地的环境开发也可以进行比对,回退等操作。Git都在本地保存了版本记录,所以大家合并起来就容易多了,等到服务器好了,直接提交就行了;或者可以随时创建一个新的中央库,随便从其他人那里复制一个然后同步就立刻恢复了中央库。
Git把数据看作是对小型文件系统的一组快照。
每次你提交更新,或保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。
为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。
Git概念理解
Git工作区域种类:
工作区(工作目录):电脑里能看到的目录
版本库( Git 仓库目录):工作区有一个隐藏目录.git,就是Git的版本库。
暂存区域:一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。
有时候也被 称作`索引',不过一 般说法还是叫暂存区域。
被管理文件的几种状态:
已修改(modified):表示修改了文件,但还没保存到本地版本库中
已暂存(staged):表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中
已提交(committed):表示数据已经安全的保存在本地版本库中
Git 工作流程:在工作目录中修改文件 à 暂存文件à将文件的快照放入暂存区域 à 提交更新,找到暂存区域的文件,将快照永久性存储到
Git 仓库目录。
下载安装
1 从Git官网直接 https://git-scm.com/downloads下载安装程序
2 安装完成后,命令行输入“git
--version”,显示如下信息表示安装成功。
3 设置用户信息,用户名称与邮件地址,每一个Git的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改
$ git config --global user.name "Your Name"
$ git config --global user.email " email@example.com "
注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都 会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
4 检查配置信息
git config --list
Git仓库
什么是Git仓库
可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
把想让git管理的文件放入此仓库下,放到其他地方Git再厉害也找不到你想管理的文件
创建Git仓库
有两种方法创建Git仓库
1 通过$ git init命令在现有目录中初始化仓库
该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的Git仓库中所有的必须文件,就是Git的版本库。
如果你是在一个已经存在文件的文件夹(而不是空文件夹)中初始化Git仓库的话,
文件并不会被跟踪,通过git add 命令来实现对指定文件的跟踪,然后执行git
commit提交
创建Git仓库
2 从一个服务器克隆一个现有的 Git 仓库
$ git clone https://github.com/test/test
在当前目录下创建一个名为“test”的目录,并在这个目录下初始化一个 .git 文件夹,从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。
如果进入到这个新建的“test”文件夹,发现所有的项目文件已经在里面了,并且都被git管理起来了,直接使用即可,无需执行add和commit命令。
也可以自定义本地仓库的名字,使用如下命令:
$ git clone https://github.com/test/test myTest
结果和上一个命令结果相同的,只是本地创建的仓库名字变为myTest。
Git 支持多种数据传输协议。上面使用的是 https:// 协议,也可以使用 git:// 协议或者使用
SSH
传输协议,比如 user@server:path/to/repo.git ,主要看git服务器的配置。
理解git文件的生命周期
工作区下的每一个文件分两种状态
已跟踪:指那些被加入了版本控制的文件,在上一次快照中有它们的记录,工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。
未跟踪:工作区中除已跟踪文件以外的所有其它文件,它们既不存在于上次快照的记录中,也没有放入暂存区
初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态
查看文件状态
$ git status
没有任何文件的打印结果
将文件添加到git版本库
$ git add xxx
git add 命令使用文件或目录的路径作为参数,如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。
使用命令 git add 开始跟踪一个文件,即把文件加入到git版本库的暂存区,将此文件变为已跟踪
被跟踪文件进入暂存状态,如果此时提交,那么该文件此刻的版本将被留存在版本库中。
暂存已修改文件
$ git add xxx
现在我们新建一个XXX.txt文件,并通过add命令将其设置为被跟踪,然后再修改XXX.txt文件内容。
Changes not staged for commit表示说明已跟踪文件的内容发生了变化,但还没有放到暂存区。
要暂存这次更新,需要运行 git
add 命令
$git add这是个多功能命令:
1 可以用它开始跟踪新文件
2把已跟踪的文件放到暂存区
Git add注意事项
如果你现在提交,那么提交的版本是你最后一次运行 git
add 命令时的那个版本,而不是在工作目录中的当前版本。所以,运行了 git
add 之后又作了修订的文件,需要重新运行 git
add 把最新版本重新暂存起来
忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表(比如日志文件,或者编译过程中创建的临时文件等)
创建一个名为 .gitignore 的文件,列出要忽略的文件模式
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。
第二行告诉 Git 忽略所有以波浪符(~)结尾的文件
tips:GitHub已经为我们准备了各种配置文件
https://github.com/github/gitignore
文件 .gitignore 的格式规范如下:
1 所有空行或者以 # 开头的行都会被 Git 忽略。
2 可以使用标准的 glob 模式匹配。
3 匹配模式可以以(/)开头防止递归。
4 匹配模式可以以(/)结尾指定目录。
5 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
所谓的 glob 模式是指 shell
所使用的简化了的正则表达式
1 星号(*)匹配零个或多个任意字符
2 [abc]匹配任何一个列在方括号中的字符
(这个例子要么匹配一个a,要么匹配一个b,要么匹配一个c)
3 问号(?)只匹配一个任意字符;
4 如果在方括号中使用短划线分隔两个字符,表示所有在这两 个字符范围内的都可以匹配
(比如 [0-9] 表示匹配所有0 到 9 的数字)
5 使用两个星号(*) 表示匹配任意中间目录
(比如`a/**/z`可以匹配 a/z, a/b/z 或 `a/b/c/z`等)
查看已暂存和未暂存的修改
$ git diff &&$ git diffxxx
git diff 命令使用文件作为参数
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,
也就是修改之后还没有暂存起来的变化内容。
将文件提交到git版本库
$ git commit –m “xxxxxxxxxxxxxxx”
使用命令 git
commit把暂存区的文件提交到git版本库;
-m后面输入的是本次提交的说明,可以输入任意内容,最好是有意义的,这样你就能从历史记录里方便地找到改动记录
tips:在此之前,请一定要确认还有什么修改过的或新建的文件还没有git
add过,否则提交的时候不会记录这些还没暂存起来的变化,这些修改过的文件只保留在本地磁盘。
所以,每次准备提交前,先用 git
status 看下,是不是都已暂存起来了, 然后再运行提交命令 git commit
重新将文件提交到git版本库
$ git commit –amend –m “xxxxxxxx”
有时候提交完了发现漏掉了几个文件没有添加,或者提交信息写错了。此时,可以运行带有 --amend 选项的提交命令尝试重新提交。
这个命令会将暂存区中的文件提交。
如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息
跳过使用暂存区域
$ git commit –a –m “xxxxxxxxxxxxxxx”
每次提交文件都需要git addàgit
commit,有没有更简单的方式呢?
给 git
commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git
add 步骤
查看已暂存和版本库的修改
$ git diff –-cached(staged ) && git diff –-cached(staged )xxx
此命令比较的是暂存区域快照和版本库之间的差异
移除文件
$ git rm xxx
git rm命令使用文件或者目录的名字,也可以使用 glob 模式
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除,然后提交。
可以用git rm命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
简单地从工作目录中手工删除文件,运行 git
status 时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到
$ git rm –-cached xxx
把文件从 Git 仓库中删除,仍然保留在当前工作目录中,换句话说,你想让文件保留在磁盘,但是并不想让
Git 继续跟踪,比如你忘记添加 .gitignore 文件,不小心把.class这样的编译生成文件添加到暂存区时
重命名文件
$ git mv xxx1 xxx2
其实,运行 git
mv 就相当于运行了下面三条命令:
$ mv README.md README
$ git rm README.md
$ git add README
查看提交历史
$ git log
工作一段时间之后,如果你想查看提交历史,可以使用git
log命令
按提交时间列出所有的更新,最近的更新排在最上面。
会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明
查看提交历史的其他格式
$ git log --pretty=oneline 显示每次提交的简略信息
$ gitlog –p 显示每次提交的内容差异,可以加上-1来仅显示最近一次提交,除了显示基本信息之外,还附带了每次commit的变化
$ git log --stat 显示每次提交的简略的统计信息
$ git log --since=2.weeks 列出所有最近两周内的提交,可以设置多种格式,比如说具体的某一天 “2008-01-15”,或者是相对地多久以前 “2years
1 day 3 minutes ago”。
暂存区和版本库回退
$ git reset HEAD xxxxxxx&& $gitreset HEAD^
git reset 命令使用文件作为参数,或者用^
上一个版本就是HEAD^,上上一个版本就是HEAD^^,往上100个版本HEAD~100 reset HEAD xxxx
暂存区回退 $ git reset HEAD xxxxxxx
暂存区和版本库回退 $ gitreset HEAD^
$ git reset --hard HEAD^
版本库回退
--hard会让工作区的文件一起回退
版本找回
$ git reset --hard 1094a
参数为commit id 1094a,版本号没必要写全,前几位就可以了,Git会自动去找
版本回退之后用git
log是再也找不到提交历史了,也就无法找到commit id,
这个时候可以用git reflog来查看你的每一次命令
撤消工作区修改
$ git checkout –
xxxx
参数为文件
如果你并不想保留对 xxx.txt 文件的修改怎么办?
该如何方便地撤消修改 ,将它还原成上次提交时的样子(刚克隆完的样子,刚把它放入工作目录时的样子)?
xxx修改后还没有被放到暂存区,撤销修改就回到和版本库一模一样的状态;
其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
Git分支
Git和传统的版本控制工具最大的区别在于分支,学习分支才能说是真正的掌握git的使用。
其他版本控制工具都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支很慢,但是在git上,无论创建、切换和删除分支,Git都很快完成。
大多数版本控制系统在创建分支时,将所有的项目文件都复制一遍,并保存到一个特定的目录。
完成这样的过程通常需要好几秒钟,有时甚至需要好几分钟,项目越大,所需时间的越长。
在 Git 中,基于Git的数据存储方式,任何规模的项目都能在瞬间创建新分支,而且分支合并也同样的简单和快速。
所以使用Git,鼓励频繁地创建和使用分支做不同的任务。
Git分支基础知识
我们假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。
暂存操作会为每一个文件计算校验和(SHA-1 哈希算法),然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用
blob
对象来保存它们),最终将校验和加入到暂存区域等待提交
当使用 git
commit 进行提交操作时,Git 会先计算每一个子目录的校验和,然后在
Git 仓库中这些校验和保存为树对象。
随后,Git 便会创建一个提交对象,该提交对象会包含一个指向快照的指针,还包含了作者的姓名和邮箱、提交时输入的信息、指向它的父对象的指针以及包含指向这个树对象的指针。
每次提交,Git 会保存一个提交对象,多次提交之后,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针
每次提交,Git都把它们串成一条时间线。
截止到目前,只有一条时间线,在Git里, 这个分支叫主分支(master),就是GIt默认分支,它就跟其它分支完全没有区别。
Git 的分支,本质上是指向提交对象的可变指针
Git 是怎么知道当前在哪一个分支上?
很简单,它有一个名为 HEAD 的特殊指针,可以将 HEAD 想象为当前分支的别名,HEAD指向的就是当前分支。
一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,
就能确定当前分支,以及当前分支的提交点:
每次提交(commit),master分支都会向前移动一步,随着你不断提交,master分支的线也越来越长
Git分支理解
当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,
通过checkout命令再把HEAD指向dev,就表示当前分支在dev上:
从现在开始,对工作区的修改和提交就是针对dev分支了,
提交一次(commit),dev指针往前移动一步,而master指针不变
假如我们在dev上的工作完成了,我们切换到master分支的时候,可以看到工作区文件是之前的
样子,所以切换分支不仅使HEAD指回master 分支,而且将工作目录恢复成 master 分支所指向的快照内容
现在我们可以把dev合并到master上,合并就是把master指向dev的当前提交,就完成了合并:
合并完分支后,可以删除dev分支。
删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支
Git分支操作
1 创建分支,要确定在哪个分支上创建子分支
$ git checkout -b dev
查看当前分支,当前分支前面会标一个*号
$ git branch
现在在dev分支上正常提交,比如对hellodongnao.txt做个修改,加上一行,然后提交
3现在我们需要将dev分支合并到master分支
现在切换到master分支上,查看文件还是master之前的提交状态,因为那个提交是在dev分支上,而master分支此刻的提交点并没有变。
$ git merge dev
git merge命令用于合并指定分支到当前分支
合并后,再查看文件内容,就可以看到,和dev分支的最新提交是完全一样的。
4 合并完成后,可以删除dev分支了
$ git branch -d dev
分支冲突解决
合并操作不会如此顺利,
如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,合并它们就会出问题。
现在我们重复上面分支的操作
1 创建一个devOne分支
2 在devOne分支上进行修改和提交操作
3 切换回master分支,对同一个文件进行修改和提交操作
4 合并devOne分支
5 删除devOne分支
HEAD指向master 分支,在======= 的上半部分,而 devOne分支在 ======= 的下半部分。
你可以选择使用由 =======分割的两部分中的一个,也可以自行合并这些内容。
分析问题出现的原因:既在devOne分支上做了修改提交,也在master分支上对同一文件做了提交,导致合并devOne分支的时候出现了问题。
发生冲突了怎么办?
hello.txt合并发生了冲突,手动解决后,对每个文件使用 git add 命令来将其标记为冲突已解决冲突再提交。
非Fast forward合并
$ git merge --no-ff
-m “xxxxxx" devTwo
因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去
我们之前说的合并分支时,Git会用Fast
forward模式,但这种模式下,删除分支后,会丢掉分支信息。
现在我们不用Fast
forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
1 创建一个devTwo分支
2 在devTwo分支上进行修改和提交操作
3 切换回master分支,用非Fast
forward的方式合并devTwo分支
4 删除devTwo分支
$ git log --graph --pretty=oneline --abbrev-commit
查看分支历史合并情况
用Fast forward模式,分支历史上就可以看出分支提交信息和分支的信息
自动非Fast forward合并
Git也会自动使用非Fast forward模式,如分支分叉的情况,git会自动使用非fast模式
这和之前合并 devTwo分支的时候看起来有一点不一样,开发历史从一个更早的地方开始分叉开来。
所以Git 帮我们做了一些额外的工作,出现这种情况的时候,Git 会使用两个分支的末端所指的快照以及这
两个分支的工作祖先(分叉点),做一个简单的三方合并。
Git也会自动使用非Fast forward模式,如分支分叉的情况,git会自动使用非fast模式
rebase
Git中除了合并,还有一种方式可以进行分支合并,就是rebase,你可以使用 rebase 命令将某一分支上(devRebase)的所有修改都移至另一分支上(master)
$ git checkout devRebase
$ git rebase master
1 首先找到这两个分支(当前分支 devRebase 、变基操作的目标分支master)的最近共同祖先 a6081ce
2 对比当前分支相对于该祖先的全部提交,提取出来存为临时文件,相当于删除这些提交,在历史中也查不到信息了
3 然后将当前分支devRebase指向目标xx1,
最后将之前另存为临时文件的修改依序应用,生成新的提交xx2。
tips:此时下面虚线部分的东西已经没有了,392aa重新提交变成了xx2,现在提交变成了直线。
$ git checkout master
$ git merge devRebase
现在回到 master 分支,进行一次快进合并。
在rebase的过程中,也许会出现冲突。Git会停止rebase并会让你去解决冲突;
在解决完冲突后,需要执行git
add命令标记为以解决, 不需要执行 git commit
$ git rebase --continue
这样git会继续应用(apply)余下的补丁。
可以用--abort参数来终止rebase的操作,并且分支会回到rebase开始前的状态
$ git rebase --abort
Rebase优点
变基使得提交历史更加整洁,向远程分支推送时能保持提交历史的整洁。
你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到origin/master上,
然后再向主项目提交修改。
这样的话,项目的维护者就不再需要进行整合工作,只需要快进合并。
使用的时候要注意,不要对在你的仓库外有副本的分支执行变基!
变基操作的实质是删除一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git
rebase 命令重新整理了提交并再次推送,你的同事因此将不得不再次将他们手头的工作与你的提交进行整合,接下来你还要拉取并整合他们修改过的提交。
Rebase与非Fast forward对比
变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。
理解变基就是将提交变成直线,然后直接快速合并。
注意无论是通过变基,还是通过非fast合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。
到底合并还是变基好?
1 如果你想看仓库的提交历史记录实际发生过什么,就算合并产生的提交历史是一团糟也没关系,
觉得它是历史文档,不能乱改,能随时查阅发生的事情,那就用非fast方式。
2 如果认为提交历史是项目过程中发生的事,只看结果,方便查阅,就用rebase。
所以看你和团队的需求
建议是对未推送给别人的本地修改执行变基操作清理历史,对已推送至别处的提交不要执行变基操作
暂存分支
$ git stash
当程序出现bug时,你就需要新建一个临时分支来修复,修复后,合并分支,然后将临时分支删除,但是你当前还在子分支上进行的工作还没有提交,而且只开发到一半,还不能提交。但是bug需要紧急修复,这个时候怎么办?
Git提供了一个stash功能,可以把当前分支暂存起来,之后可以恢复继续开发
现在我们创建一个子分支来修复bug。
1首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建分支
2 现在修复bug,需要把“hello devTwo
branch”改为“hello devTwo branch
to bug”,然后提交:
3 修复完成后,切换到master分支并合并bug001分支
4 删除bug001分支
Bug修复完成了,我们回到devThree分支继续之前的开发
1 查看我们的暂存分支
$ git stash list
2 恢复我们的暂存分支
a:一是用gitstash apply xxx恢复,stash内容并不删除,还需要git stash
drop来删除;
b:另一种方式是用gitstash pop,恢复的同时把stash内容也删了:
3 我们接着完成devThree的工作
删除已经提交(未合并)的分支
$ git branch -D xxxxx
1 我们新建了 一个分支,已经完成了并提交(commit)的开发,但是这个时候不需要此需求了,应该把此分支删除。
补丁patch
补丁并不是针对所有代码的修改,只是针对于局部的修改。
在代码的维护中,如果只修改一部分代码,需要将代码完整的克隆下来,可是修改的只是很小的一部分;在这种情况下可以将一些代码的补丁信息发送给开发者,开发者收到之后知道那些代码被修改了,这样就可以使用一个极低的开销实现代码的修改操作
在git中提供了两种补丁方式
1使用gitdiff生成标准的patch
2 使用git format-patch声明git专用的patch
Git diff生产标准的patch
A 贡献者
1 创建一个testPatchDiff分支
2 在testPatchDiff分支上进行代码修改
3 使用git diff xx 查看修改
4 在testPatchDiff分支上进行提交
5 使用git diff master> testDiff创建补丁信息testDiff
6 删除testPatchDiff分支
B 开发者
1 cat testDiff查看有哪些修改
2 切换到master分支
3 创建一个新的applyPatchDiff分支
4 使用git apply testDiff 应用补丁信息testDiff
5在applyPatchDiff分支上进行提交补丁操作
6 切换回master分支合并applyPatchDiff分支
7 删除applyPatchDiff分支
git format-patch声明git专用的patch
A 贡献者
1 创建一个testPatchFormat分支
2 在testPatchFormat分支上进行代码修改
3 使用git diff xx 查看修改
4 在testPatchFormat分支上进行提交
5 使用git format-patch master与原始代码做一个比较,比较之后会自动生成补丁文件
6删除testPatchFormat分支
B 开发者
1cat 0001-testPathcFormat.patch查看有哪些修改(像是一封邮件,可以将文件粘贴 进电子邮件客户端,也可以通过命令行gitsend-email发送它)
2 切换到master分支
3 创建一个新的applyPatchFormat分支
4 使用git am 0001-testPathcFormat.patch应用补丁信息
5 切换回master分支合并applyPatchDiff分支
6 删除applyPatchFormat分支
补丁两种方式比较
git diff生成的Patch兼容性强。如果你修改的代码不是Git管理的版本库,那么必须使用git
diff生成的patch才能让你的代码被项目的维护人接受。
但是如果你是向公共的开发社区进行代码的补丁更正,建议使用git format-patch,这样不仅标准,而且也可以将作者的信息公布
GitFlow理解
GitFlow 是由
Vincent
Driessen 提出的一个
git操作流程标准,包含如下几个关键分支:
master:主分支,非常稳定的,不用来开发和发布,只用来跟踪已经发布的代码;
develop:主开发分支,包含确定即将发布的代码;开发都在这个分支;
到发布时,再合并到release上;
feature:新功能分支,一般一个新功能对应一个分支,对于功能的拆分需要比较合理,以 避免一些后面不必要的代码冲突;
release:发布分支,发布时候用的分支,测试时候发现的
bug直接 在这个分支进行修复;
hotfix:紧急修 bug
的时候用;
我们想在开发要开发一个新功能,基于develop分支创建feature分支
完成后再合并到 develop 分支上,等待发布
当需要发布时,我们从 develop 分支创建一个 release 分支
然后这个 release 分支会发布到测试环境进行测试,如果发现问题就在这个分支直接进行修复。
发布结束后,这个 release 分支会合并到
develop
和 master
分支,从而保证不会有代码丢失
hotfix 分支的作用是紧急修复一些 Bug。它们都是从
master
分支上建立,修复结束后再合并到
develop
和 master
分支上。
GitFlow的好处
并行开发:
每个新功能都会建立一个新的 feature分支,从而和已经完成的功能隔离开来,而且只有在新功能完成开发的情况下,其对应的 feature分支才会合并到主开发分支(develop分支)
协作开发:
每个 feature分支多人协同开发。
发布阶段:
当 feature 开发完成的时候,它会被合并到 develop 分支,这个分支主要用来暂时保存那些还没有发布的内容,所以如果需要再开发新的 feature,我们只需要从 develop 分支创建新分支,即可包含所有已经完成的 feature 。
紧急修复:
hotfix(bug) 分支,这种类型的分支是从master分支上创建出来并做一个紧急的修复,而且这个紧急修复只影响这个已经发布的 版本,而不会影响到你正在开发的新 feature。
Git远程仓库
GitHub是一个免费的服务器,这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库
注意GitHub上免费托管的Git仓库,任何人都可以看到
有了GitHub帐号之后,并不是说就可以直接使用了,还需要创建SSH
Key。
1 在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Git
Bash,创建SSH Key:
$ ssh-keygen -t rsa -C "youremail@xxx.com"
里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥,id_rsa是私钥,id_rsa.pub是公钥
2 登陆GitHub,打开“Account settings”,“SSH and GPG keys”页面:
然后,点“New Ssh key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容
那么此时表示已经和GitHub之间建立好了一个安全链接。
由于ssh存在,GitHub才能进行用户识别。
GitHub允许你添加多个Key。
添加远程库
在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过远程仓库来协作。
1首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库。
2 在Repository name填入testGit,其他保持默认设置,点击“Create repository”按钮,就成功地创建了一个新的Git仓库
现在设置的仓库名称为testGit,仓库创建完成之后会给出两种链接方式
a: https://github.com/xx/testGit.git
b: git@github.com:xx/testGit.git
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
3目前,在GitHub上的这个testGit仓库还是空的,GitHub告诉我们,可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联。
现在,把GiuHub与本地仓库关联,在本地的testGit仓库下运行命令
$ git remote add origin git@github.com:xxxxxxx/testGit.git
xxxxx为你自己的GitHub帐号
远程库仓库的名字就是origin,这是Git默认的叫法,也可以改成别的
此时已经和远程仓库建立了链接,但是远程仓库里面并没有本地仓库的内容
4 下一步,就可以把本地库的所有内容推送到远程库上:
$ git push -u origin master
把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令以后直接运行
$ git push origin master
把本地master分支的最新修改推送至GitHub
5 查看GitHub是有添加了本地内容
tips:当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:
Theauthenticity of host 'github.com (xx.xx.xx.xx)'
can't be established.
RSAkey fingerprint isxx.xx.xx.xx.xx.
Areyou sure you want to continue connecting (yes/no)?
这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,
需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。
这个警告只会出现一次,后面的操作就不会有任何警告了
提交文件到远程仓库
1 修改xxx.txt并提交
2 此时的修改都属于本地仓库master分支,下面提交到远程仓库master分支
$ git push origin master
远程仓库其他操作
使用https建立一个test远程仓库
$ git remote add test https://github.com/xxxxx/xxxGit.git
查看远程仓库信息,如果没有推送权限,就看不到push的地址
$ git remote && $gitremote -v
切换远程仓库
$ git remote set-url
origin git@github.com:xxxxx/xxxGit.git
删除远程仓库
$ git remote rm test
从远程库克隆
之前先有本地库,后有远程库的时候,如何关联远程库。
现在先创建远程库,然后,从远程库克隆。
1 首先,登陆GitHub,然后,在右上角找到“Create
a new repo”按钮,创建一个新的仓库helloGit。
我们勾选Initialize this repository with a README表示自动为用户进行仓库的初始化,并且这样GitHub会自动为我们创建一个README.md文件。
2 现在,远程库已经准备好了,下一步是用命令git
clone克隆一个本地库,不要在xxxGit目录下操作,直接换一个新目录helloGit。
$ git clone git@github.com:xxxxx/helloGit.git
3 再尝试下提交文件到远程仓库
克隆其他开源项目
不要认为GitHub就是一个远程仓库,它上面有不少开源项目,如bootstrap,mybatis
如:https://github.com/mybatis
1 但是这个上面下载下来的代码是不能够进行修改的,因为这个主文件只能由用户发出补丁,而后由开发者进行修改。如果要是参考源码或者修改,可以将项目克隆过来(fork)
2 进入自己的帐号下,获取到远程仓库的地址,之后可以在本地仓库中将代码克隆下来。
$ git clone git@github.com:xxxxx/mybatis.git
tips:如果从mybatis的作者的仓库地址克隆,因为没有权限,你将不能推送修改。
协同开发
单分支开发
1 A修改其中一个文件并commit和push
2 B修改另外一个文件并commit和push(能不能push成功?)
两个开发者并没有编辑同一个文件,但Git要求在本地合并提交。B必须抓取A的改动并合并它们,才能被允许推送。
$ git fetch <远程主机名>
//这个命令将某个远程主机的更新全部取回本地
$ git fetch <远程主机名>
<分支名> //取回特定分支的更新,可以指定分支名
3 B执行fetch取回服务器的更新(可以通过git
log –p FETCH_HEAD查看更新信息)
4 B合并远程分支到自己的master分支
$git merge origin/master
6 于此同时A还在开发,commit之后准备push
7 A想要push,也得先执行fetch拉取服务器的更新并合并再提交
分支其他操作
分支更名
$ git branch –m xxx1 xxx2 xxx1为原来分支名称,xxx2为新分支名称
查看分支
$ git brance –a 查看全部分支,包括远程和本地
$ git brance –r 查看远程分支
$ git brance –l 查看本地分支
删除远程分支
$ git push origin --delete xxxxx
标签
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。
Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。
创建标签
在Git中打标签非常简单,首先,切换到需要打标签的分支上
$ git tag xxxx
默认标签是打在最新提交的commit上的。如果想在之前的commit上打标签,先找到历史提交的commit
id,然后打上就可以了:
$ git tag v0.9 67cda3
可以用命令git
tag查看所有标签:
$ git tag
还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$git tag -a xxxx -m “xxxxx" xxxxx
查看标签信息
$ git show xxx
操作标签
本地标签删除
$ git tag -d xxxx
推送本地标签到gitHub
$ git push origin xxxx
推送全部尚未推送到远程的本地标签
$ git push origin --tags
删除远程仓库标签
1 先删除本地标签
$ git tag -d xxxx
2 从远程删除
$ git push origin :refs/tags/xxxxxx
搭建GitLab服务器
GitHub是一个免费的服务器,这个网站就是提供Git仓库托管服务的,如果公司开发使用的话,会有几个问题
1网络不稳定
2代码是公开的,大家都可以查看
如果你需要一个私有的托管服务,支付每个月7美元购买5个私有库,想要更多的私有仓库则要交更多的钱
最好的方法就是在你的服务器上运行 Git。不仅你能够省去一笔钱,你还能够在你的服务器有更多的操作。
在linux上有两种方式部署git服务器
1 使用名为 GitLab 的
GUI
工具
2 运行一个纯Git 服务器
GitLab 是一个非常优秀的项目,这是一个开源项目,允许用户在自己的服务器上运行类似于
GitHub 的项目管理系统,使用
GitLab 为团队成员或公司运行类似于
GitHub 的服务,可以使用
GitLab 开发私有项目。
安装之前,请确保你的服务器是否安装了
ssh rpm -qa|grep -E
"openssh"
防火墙 rpm-qa|grep-E "firewalld"
wget rpm -qa|grep -E
"wget"
1 安装 GitLab 之前,需要配置
SMTP
电子邮件服务器,以便
GitLab 可以在需要时随时推送电子邮件。官方推荐使用
Postfix。先在你的服务器上安装
Postfix
# yum install postfix 安装命令
# systemctl enablepostfix 开机自启动
# systemctl startpostfix 启动postfix
2添加GitLab镜像源,其他镜像下载地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/
# wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm
3 安装gitlab
# rpm -i
gitlab-ce-10.0.0-ce.0.el7.x86_64.rpm
4 修改gitlab配置文件指定服务器ip和自定义端口
# vim /etc/gitlab/gitlab.rb
external_url `http://192.168.1.149:8900` 服务器ip和未被占用的端口
unicorn[‘port’]=8899 默认8080,设置未被占用端
5 重置gitlab配置文件
# gitlab-ctl
reconfigure
6 重启gitlab
# gitlab-ctl
restart
7 访问gitlab,直接输入上面配置的ip加端口访问即可
初始账户: root 密码:5iveL!fe
8 设置gitlab发信功能,发信系统用的默认的postfix,smtp是默认开启的,两个都启用了,两个都不会工作,可以自己选择
a 设置关闭smtp,开启postfix
# vim /etc/gitlab/gitlab.rb
gitlab_rails['smtp_enable']
= false
b 关闭postfix,设置开启smtp
https://docs.gitlab.com/omnibus/settings/smtp.html
测试是否可以邮件通知:登录并添加一个用户,我这里使用qq邮箱添加一个用户,登录qq邮箱,
可以收到邮件通知(也可在linux执行echo "test mail"|mail -s "postfix mail title" 123456789@qq.com)
如果收不到,请查看垃圾邮箱或者检查邮件是否被拦截并删除,如果有请添加到白名单
并删除用户再重新添加用户就可以收到了,否则请检查邮件日志并做好相关设置
tips:
1 如果gitlab报502错误,一般是权限问题,解决方法:# chmod -R
755 /var/log/gitlab
如果还不行,请检查你的内存,安装使用GitLab需要至少4GB可用内存,否则出现各种诡异的问题,
而且在使用过程中也经常会出现500错误.
2 gitlab-ctl reconfigure:
Errorexecuting
action `run` on resource 'execute[/opt/gitlab/embedded/bin/initdb-D /var/xxxx‘
文件/etc/passwd的权限是600,给予644权限后,解决问题