一、Git仓库的基本概念和流程
1、git仓库的基本概念
远程仓库(Remote):
也叫作资源库,是远程机器上的代码库,用于做不同版本库文件交换更新。如Gitlab,GitHub,gitee。
本地库(Repository):
是用户在本地创建的目录,拥有远程库的一个快照,由工作区和版本库构成。
工作区(Workspace):
本地库的根目录中除.git目录以外的内容,存储内容的实际文件。
暂存区(stage/Index):
也叫做缓存区,暂存信息存放在.git目录"下的index文件(.git/index)中,用于临时保存内容的修改;
版本库(.git目录)
是本地库的根目录中的一个隐藏目录.git,用于记录版本信息,Git进行版本控制所需要的文件,则都放在.git文件夹中;
分支(Branch):
本地库中默认创建一个主(master)分支,分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。
本地库和远程库的关系
开发人员通过Git命令来管理代码,最常用的6个命令如下图所示:
2、git仓库的工作流程
从一般开发者的角度来看,使用Git的工作流程是:
1.克隆远程库:从远程库上克隆完整的Git仓库(包括代码和版本信息)到本地;
2. 在本地库上修改代码:在本地库上根据不同的开发目的,创建分支,修改代码;
3.提交到分支:在本地分支上提交代码;
4.把修改合并到本地主分支:在本地库上提交更新,也就是说,把修改合并到本地主分支;
5.把远程库合并到本地主分支:把远程库上的最新代码fetch下来,跟本地主分支合并,如果存在冲突,那么解决冲突。
6.把本地主分支提交到远程库:生成补丁(patch),把补丁发送给远程库。
二、Git命令
1、创建版本库
创建一个空文件夹作为版本库,这里取名为gitTest,右键通过命令行打开bash窗口
git init命令将目录变成git可管理的仓库
文件夹中出现隐藏的.git目录,说明版本库创建成功。对于大型项目的管理一般会屏蔽一些与代码无关的内容,创建版本库成功后,最好先创建.gitignore文件对无关内容的忽略。此处的版本库只做为练习内容,不做.gitignore的处理。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
这时候你当前testgit目录下会多了一个.git的目录,这个目录是Git来跟踪管理版本的,没事千万不要手动乱改这个目录里面的文件,否则,会把git仓库给破坏了。.git里面内容如下:
2、添加文件和版本回退
所有的版本控制系统,只能跟踪文本文件的改动,比如txt文件,网页,所有程序的代码等,图片、视频等二进制文件版本控制系统只能知道是否有改动,具体改动系统也不清楚。
1.vi 创建文件Hello.java
使用vi命令创建java文件,创建好后此文件在工作区
2.git status 查看文件状态
git status命令查看文件追踪状态
3.git add 提交文件到暂存区
如果有多个文件可以使用 git add . 或 git add 进行提交,如:
创建六个txt文件用于多文件提交
使用不同方式进行git的提交
4.git rm --cached 对指定文件撤回到工作区
将 test.txt 撤回到工作区
如果不指定文件名,则不能执行撤回
5. git commit -m "commit log" 提交到主分支
目前暂存区中已经有六个文件了,除了刚刚撤回的test.txt都在暂存区中,将暂存区的文件都发送到主分支上
查看提交状态
test.txt还在工作区中,暂存区中已经没有文件了
6.git log 查看提交日志
git log命令显示从最近到最远的显示日志,我们可以看到最近三次提交
我们在master分支上做了两次提交
如果嫌上面显示的信息太多的话,我们可以使用命令git log --pretty=oneline
7.git reset --hard HEAD^进行版本回退
将当前的版本回退到上一个版本
(1)git reset --hard HEAD^
如果想回退到上上个版本使用git reset --hard HEAD^^即可
如果回退到前10个或更多版本,git reset --hard HEAD~100即可
(2)git reset --hard sha1前六位
日志中黄色字体commit 后就是sha1号,可以根据前六位进行版本回退
8.git reflog查看历史版本号
使用git reset --hard 489db8回退到此版本
此时不想回退到489db8的版本,但是git log中查看不到f0d7fdd的版本:
git reflog 查看历史版本号
此时则可以回退到f0d7fdd的版本
3、删除文件
目前添加并且提交了多个文件
一般情况下,可以直接在文件目录中把文件删了,或者使用如上rm命令:git rm test.txt ,如果想彻底从版本库中删掉了此文件的话,可以再执行commit命令提交。
发现删除的文件直接进入暂存区。进入暂存区可以退回工作区,使用下面命令 : git reset HEAD ,这里使用test.txt测试,filename换成test.txt即可
这里新建test6.txt辅助查看文件位置。
暂存区中的test.txt 被删除和 test6.txt 提交。
4、Git配置信息
git中,使用 gitconfig 命令用来配置git的配置文件,git 配置级别主要有以下3类:
1、仓库级别 local 【优先级最高】
2、用户级别 global【优先级次之】
3、系统级别 system【优先级最低】
git 仓库级别对应的配置文件是当前仓库下的.git/config
git 用户级别对应的配置文件是用户宿主目录下的~/.gitconfig
git 系统级别对应的配置文件是git安装目录下的/etc/gitconfig
可以在cmd命令提示符中输入以下查看配置信息
共享git时,一般设置仓库级别
不共享电脑时,设置用户级别
系统级别一般不涉及
1.git config --local/global/system -l查看配置信息
git config --local -l 查看仓库级别配置信息
git config --global -l 查看用户级配置信息
git config --system -l 查看系统级配置信息
2.git config 修改config
修改用户名和邮箱:
git config --global user.name "goose"
git config --global user.email "goose@163.com"
注意不要手动修改 每个级别的配置文件,要用命令。
对于git来说,配置文件的权重是仓库>全局>系统。Git会使用这一系列的配置文件来存储你定义的偏好,它首先会查找/etc/gitconfig文件(系统级),该文件含有对系统上所有用户及他们所拥有的仓库都生效的配置值。接下来Git会查找每个用户的~/.gitconfig文件(全局级)。最后Git会查找由用户定义的各个库中Git目录下的配置文件.git/config(仓库级),该文件中的值只对当前所属仓库有效。
5、 .gitignore 文件
在使用git的过程中,一般我们总会有些文件无需纳入git的管理,也不希望它们总出现在未跟踪文件列表,这些文件通常是日志文件、临时文件、编译产生的中间文件、工具自动生成的文件等等。
此时我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式,Git会根据这些模式规则来判断是否将文件添加到版本控制中。注意:在windows下可以创建文件名为.gitignore.,保存之后系统会自动重命名为 .gitignore
1.格式规范
所有空行或者以注释符号 # 开头的行都会被 Git 忽略
可以使用标准的 glob 模式匹配
匹配模式最后跟斜杠(/)说明要忽略的是目录
要忽略指定模式以外的文件或目录,可以在模式前加上感叹号(!)进行取反
2.glob模式
glob 模式是指 shell 所使用的简化了的正则表达式,匹配规则如下:
"*":星号匹配零个或多个任意字符
[]:匹配任何一个列在方括号中的字符,如[ab]匹配a或者匹配b
"?":问号匹配一个任意字符
[n-m]:匹配所有在这两个字符范围内的字符,如[0-9]表示匹配所有0到9的数字
匹配示例
logs/: 忽略当前路径下的logs目录,包含logs下的所有子目录和文件
/logs.txt: 忽略根目录下的logs.txt文件
*.class: 忽略所有后缀为.class的文件
!/classes/a.class:不忽略classes目录下的a.class文件
tmp/*.txt: 只忽略tmp目录下的.txt文件
**/foo: 可以忽略/foo, a/foo, a/b/foo等
3.定义全局的 .gitignore
除了可以在项目中定义.gitignore文件外,还可以设置全局的.gitignore文件来管理所有Git项目的行为。
这种方式在不同的项目开发者之间是不共享的,是属于项目之上Git应用级别的行为。
可以在任意目录下创建相应的.gitignore文件,然后再使用以下命令配置Git
git config --global core.excludesfile ~/.gitignore
4..gitignore 规则不生效
.gitignore只能忽略那些原来没有被 track 的文件,如果某些文件已经被纳入了版本管理中,则修改 .gitignore 是无效的。所以在项目开始就要创建 .gitignore 文件。
6、git diff 命令查看文件变动
对test1.txt做简单修改
对 test1.txt 进行提交
使用git diff 命令不会显示变化,这是因为test1.txt 已经提交到Git仓库了,直接使用diff命令只能查看文件在 工作区和暂存区的差别
工作目录 vs 暂存区
$ git diff
意义:查看文件在工作目录与暂存区的差别。如果还没 add 进暂存区,则查看文件自身修改前后的差别。也可查看和另一分支的区别。
git diff
暂存区 vs Git仓库
git diff --cached
意义:表示查看已经 add 进暂存区但是尚未 commit 的内容同最新一次 commit 时的内容的差异。 也可以指定仓库版本:
git diff --cached
工作目录 vs Git仓库
git diff
意义:查看工作目录同Git仓库指定 commit 的内容的差异。
=HEAD时:查看工作目录同最近一次 commit 的内容的差异。
Git仓库 vs Git仓库
git diff
意义:Git仓库任意两次 commit 之间的差别。
以上命令可以不指定 ,则对全部文件操作。以上命令涉及和 Git仓库 对比的,均可指定 commit 的版本。
HEAD 最近一次 commit
HEAD^ 上次提交
HEAD~100 上100次提交
三、分支管理
Git 的默认分支就是master。你所作的commit会在master分支上自动移动。在多次提交操作之后,master分支指向最后那个commit object(提交对象链)。
Git 的 “master” 分支并不特殊,跟其它分支没有区别。之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它。
master分支往往有一种 这个分支是稳定、无bug的分支。而develop往往预示这新功能,不稳定的分支。这和分支策略有关,但本质上这两个分支没区别。
1、git branch 创建分支
git branch dev 创建 dev 分支
git branch 查看所有分支,当前分支使用*表明并绿色显示
2、 git checkout 切换分支
git checkout dev 切换到 dev 分支
3、git checkout -b 创建并切换分支
git checkout -b dev2 创建并切换到 dev2 分支
这时在dev2分支创建一个文件a.txt并且提交。我们发现在dev2分支可以看到这个文件,当我们切换会master时候无法看到这个文件。
未提交文件 a.txt 时在 master 分支上可以看到 a.txt
在dev2上完成 a.txt 的提交
此时只能在 dev2 上看到 a.txt 文件
4、git branch -d 删除分支
不能删除目前所在的分支
不能删除还没合并的分支,dev2 中提交了一个a.txt文件,但是还没和 master 合并,也不能删除。
git branch -D 可以强制删除
5、git merge 合并分支
切换到 master 上对dev2 进行分支的合并
master 分支上可以看到 a.txt 文件了
分支的本质
master指向的是提交
HEAD是指向当前的分支,当前在哪个分支就指向哪个分支
创建了dev的分支,切换到dev分支的时候HEAD就会指向dev
进入 .git 文件夹查看 HEAD 的内容的时候可以看到,所处分支不同内部的文件指向就不同。
master 分支下
dev2 分支下
如果 dev2 发生修改提交,dev2 的版本就会向右移动。
在 master 分支上进行合并,master 和 dev2 的版本相同
6、分支冲突
上图表示,在不同分支修改同一个文件,修改内容不同,会导致分支合并时,git 无法确定保留哪个分支的版本,导致分支冲突。如果修改内容相同,则不会分支冲突
在 dev2 分支里面修改 a.txt 文件添加一行 update by dev2 后提交,
在 master 分支里面修改 a.txt 文件添加一行 update by master 后提交,
在 master 分支中进行 merge ,发生分支冲突
<<<<<<<<<<HEAD是当前指向的分支所修改
>>>>>>>>>>dev2是 dev2 分支修改
此时需要手工合并。
如果保留 master 的内容,不修改dev2 中内容时,还会发生分支冲突。