git详细教程

1 版本控制系统

版本控制系统,VCS(Version Control System),是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。历史上版本控制系统的演进又以下三种:

1.1 本地版本控制系统

采用某种简单的数据库或硬盘来记录文件的历次更新差异。RCS就是代表性的本地版本控制系统。

在这里插入图片描述

1.2 集中化版本控制系统

为了让不同系统上的开发者协同工作,集中化版本控制系统(Centralized Version Control Systems,简称CVCS)应运而生。

代表产品CVS、Subversion 、 Perforce 以及当下使用广泛的SVN。

集中化版本控制系统有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。

优点:特别是相较于老式的本地 VCS 来说,CVCS允许多人协同工作,而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

缺点:依赖中央服务器,用户本地只有自己以前所同步的版本,每次都需要联网拿到服务器的最新版本,如果中央服务器出现单点故障,就会造成数据丢失。

在这里插入图片描述

1.3 分布式版本控制系统

分布式版本控制系统(Distributed Version Control System,简称 DVCS)解决了集中式版本控制系统的弊端。客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。用户在本地仓库做版本控制,需要与其他用户交互时才联网push到服务器。

代表产品有Mercurial、Bazaar 、 Darcs 以及Git

分布式版本控制系统功能强大,不可避免地增加了本地存储空间的占用,逻辑较为复杂。

在这里插入图片描述

1.4 git的优缺点

优点:

  • 适合分布式开发,强调个体。
  • 公共服务器压力和数据量都不会太大。
  • 速度快、灵活。
  • 任意两个开发者之间可以很容易的解决冲突。
  • 离线工作。

缺点:

  • 模式上比SVN更加复杂。
  • 代码保密性差。

2 git相关术语

  1. 仓库(Repository):受版本控制的所有文件修订历史的共享数据库
  2. 工作空间(Workspace) :本地硬盘上的文件
  3. 工作树/区(Working tree):工作区中包含了仓库的工作文件
  4. 暂存区(Staging area):用来暂存Workspace文件commit之前的变化,通过git add命令添加到暂存区。
  5. 索引(Index):即暂存区
  6. 本地仓库(Local Repository):本地完整的文件版本仓库
  7. 历史库(History):即本地仓库
  8. 远程仓库(Remote Repository):服务器的文件版本仓库
  9. 跟踪(track):将本地文件赋予git版本控制功能
  10. 签出(Checkout):从仓库中将文件的最新修订版本复制到工作空间
  11. 提交(Commit):对各自文件的工作副本做了更改,并将这些更改提交到仓库,提交可以是名词,代表提交的仓库版本
  12. 推送(Push):将本地仓库的版本推送到远程仓库
  13. 冲突(Conflict):多人对同一文件的工作副本进行更改,并将这些更改提交到仓库
  14. 分支(Branch):从主线上分离开的副本,默认分支叫master
  15. 头(HEAD):头是一个象征性的参考,最常用以指向当前选择的分支。
  16. 修订(Revision):表示代码的一个版本状态。Git通过用SHA1 hash算法表示的ID来标识不同的版本。
  17. 标记(Tags):标记指的是某个分支某个特定时间点的状态。通过标记,可以很方便的切换到标记时的状态。
  18. 锁(Lock):获得修改文件的专有权限。

3 git配置

3.1 git三个配置文件

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置,分别代表三个不同级别的配置,系统配置、用户配置、当前仓库配置:

  • /etc/gitconfig 文件: (windows系统该文件在git安装目录/Git/mingw64/etc/gitconfig),包含系统上每一个用户及他们仓库的通用配置。 如果使用带有 --system 选项的 git config 时,它会从此文件读写配置变量。例如,打开git bash工具,键入:

    git config --system user.name 张三
    
  • ~/.gitconfig~/.config/git/config 文件:(windows系统该文件在用户目录/gitconfig),只针对当前用户。 可以传递 --global 选项让 Git 读写此文件。

    git config --global user.name 张三
    
  • 当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。

    git config --local user.name 张三
    

当三个配置文件有配置项重复时,每一个级别覆盖上一级别的配置,当前仓库配置覆盖用户配置,用户配置覆盖系统配置。

*git bash是个shell命令工具,可以在windows上敲各种bash shell命令,还可以使用vim哦

相关命令

查看所有配置项(相同配置项按文件级别覆盖):

git config -l

查看指定配置项(以用户名为例,下同)

git config --get user.name

查看配置项,使用正则表达式匹配

git config --get-regexp user.*

删除配置项

git config [--local|--global|--system] --unset user.name

为git命令设置别名

git config [--local|--global|--system] alias.ci commit #用ci代替commit

更多用法键入git config会显示help

3.2 .gitignore文件

在工作空间中有些文件不需要纳入git版本控制,比如编译生成的.class文件,IDE相关的文件(.ipr、.idea、.setting等)、数据库相关文件等等。

此时可以在主目录下建立".gitignore"文件,然后在里面配置需要忽略的文件,文件内容规则如下图:

在这里插入图片描述

.gitignore文件定义的文件将不受git版本控制管理,执行git add .时这些忽略的文件不会添加到暂存区。

4 git文件操作

4.1 git工作原理

在进行提交操作时,Git 会保存一个提交对象(commit object)。使用git log可以查看每一个commit object的对象信息。

Git会在暂存操作时使用SHA-1哈希算法为每一个要暂存文件计算校验和,然后会把当前版本的文件快照保存到 Git 仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交。

当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。 随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。

提交完成后,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。

4.2 git工作区

Git本地有三个工作区域:工作目录(Workspace)、暂存区(Stage/Index)、本地资源库(Repository或History)。加上远程的git仓库(Remote Repository)一共四个工作区域。文件在这四个区域之间的转换关系如下:

在这里插入图片描述

4.3 git文件状态

根据文件保存到工作区的不同,就有四种文件状态:

  • Untracked: 未跟踪,此文件不受git版本控制. 通过git add filename命令状态变为Staged,通过git clean -df filename命令可删除未跟踪文件。
  • Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件
  • Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改
  • Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

四种状态的转换如下图:

在这里插入图片描述

使用git status命令查看文件状态。

4.4 git文件操作命令

  1. init:在当前目录初始化一个版本库,会生成.git文件夹。之后可以关联远程分支

    #初始化版本库
    $ git init
    
  2. clone:克隆远程仓库到本地,完成之后工作区文件状态都是Unmodified

    #克隆远程仓库到本地
    $ git clone https://github.com/yozzs/xxx.git
    
  3. add:将untracked或modefied状态的文件添加到暂存区

    # 添加指定文件到暂存区
    $ git add [file1] [file2] ...
    
    # 添加指定目录到暂存区,包括子目录
    $ git add [dir]
    
    # 添加当前目录的所有文件到暂存区
    $ git add .
    
  4. commit:将暂存区或工作空间(-a)提交到本地仓库

    # 提交暂存区到仓库区,message是提交的信息,用户自己写。如果不用-m选项,则会跳转到vi页面编写提交信息,写完:wq保存退出,如果不写提交信息直接退出则提交失败
    $ git commit -m [message]
    
    # 提交暂存区的指定文件到仓库区,在分支冲突的状态下不能指定文件提交
    $ git commit [file1] [file2] ... -m [message]
    
    # 提交工作区自上次commit之后的变化,直接到仓库区,跳过add,对新文件无效
    $ git commit -a
    
    # 提交时显示所有diff信息
    $ git commit -v
    
    # 使用一次新的commit,替代上一次提交,如果代码没有任何新变化,则用来改写上一次commit的提交信息
    $ git commit --amend -m [message]
    
    # 重做上一次commit,并包括指定文件的新变化
    $ git commit --amend [file1] [file2] ...
    
  5. revert:撤销提交

    # 把指定的提交的所有修改回滚,并同时生成一个新的提交
    $ git revert <commit-id>
    
  6. push:将指定本地分支推送到指定的远程主机

    # 上传本地指定分支到远程仓库,remote默认为origin
    $ git push [remote] [localbranch]:[remotebranch]
    
    # 强行推送当前分支到远程仓库,即使有冲突
    $ git push [remote] --force
    
    # 推送所有分支到远程仓库
    $ git push [remote] --all
    
  7. pull:拉取远程仓库的版本,并与本地分支合并,可以理解为git fetch+git merge

    # 拉取远程仓库指定分支的变化,并与指定本地分支合并,remote为远程主机名,默认origin
    $ git pull [remote] [remotebranch]:[localbranch]
    
    # 如果合并到当前分支,省略本地分支名
    $ git pull [remote] [remotebranch]
    
    # 如果当前分支已指定追踪远程分支,可省略远程分支名
    $ git pull [remote] 
    
    # 如果当前分支只有一个追踪分支,连远程主机名都可以省略
    $ git pull
    

    注意,分支推送顺序的写法是<来源地>:<目的地>,所以git pull是<远程分支>:<本地分支>,而git push是<本地分支>:<远程分支>。

  8. fetch:获取远程仓库的变动到本地仓库,不合并本地分支

    # 获取远程仓库所有更新,但不自动合并当前分支
    $ git fetch [remote]
    
  9. remote:操作远程仓库

    # 简单查看单个仓库名
    $ git remote
    
    # 显示所有远程仓库
    $ git remote -v
    
    # 显示某个远程仓库的信息
    $ git remote show [remote]
    
    # 增加一个新的远程仓库,并命名
    $ git remote add [shortname] [url]
    
    # 修改远程仓库
    $ git remote rename [oldname] [newname]
    
    # 删除远程仓库
    $ git remote rm [remote-name]
    
  10. log:查看提交日志,会vi进入log文件。会显示每一次提交的commit_id、分支、作者、日期信息。

       # 查看提交记录
       $ git log  #可通过管道和其他shell命令操作,获得想要的统计结果
       
       # 查看提交记录,显示最近5次提交
       $ git log -5
       
       # 以图形化的方式显示提交历史的关系,可以直观地看到分支合并情况
       $ git log --graph
       
       # 查看这个仓库中所有的分支的所有更新记录,包括已经撤销的更新
       $ git reflog
    
  11. rm:删除版本库或暂存区的文件

    # 只删除暂存区文件,工作空间和仓库不变
    $ git rm --cached <file>
    
    # 删除本地仓库文件,会同时删除工作空间和暂存区该文件
    $ git rm -f <file>
    
  12. clean:清理工作区未跟踪状态文件(不会清除.gitignore指定文件)

    # 删除工作区未跟踪状态文件
    $ git clean -df  #-d表示包含目录,-f表示强制清除
    
    # 删除指定未跟踪状态文件
    $ git clean -f <file>
    
  13. reset:回退文件的本次修改,resetgit rm --cache的区别是前者重写本地仓库的版本,效果可以是回退添加或修改,后者是删除暂存区文件。

    # 将本地仓库指定文件的版本重写到暂存区
    $ git reset HEAD <file> #HEAD表示HEAD指向的提交
    
    # 放弃工作区和index的改动,同时HEAD指针指向前一个commit对象,一个commit对象实际就是一个仓库的版本。效果就是撤销提交。HEAD~1也可以改为HEAD~n,n表示前n个提交
    $ git reset --hard HEAD~1
    
    #功能同上,一个^表示前一次提交,^^表示前两次提交
    $ git reset --hard HEAD^
    
    #将HEAD,index(暂存区)和workspace全部重置为指定某次提交的目录树
    $ git reset --hard <commit_id>
    
    #只将HEAD重置为指向指定某次提交的目录树,不重置工作区和暂存区
    $ git reset --soft <commit_id>
    
    #只将HEAD和index重置为指向指定某次提交的目录树,不充值工作区
    $ git reset --mixed <commit_id>
    
  14. checkout:签出,用暂存区或仓库的目录树替换工作区目录树。会修改工作空间,所以很危险。但是也很常用。

    # 用暂存区目录树替换工作空间。此操作会删除本地未暂存的modified文件,慎用
    $ git checkout .
    
    # 用暂存区目录树指定文件替换工作空间该文件。
    $ git checkout -- <file>
    
    # 用HEAD指向的分支(默认是master)仓库目录树指定文件替换工作空间该文件。
    $ git checkout HEAD -- <file>
    
    # 检出branch分支,更新HEAD以指向branch分支,然后用branch分支指向的树指定文件替换工作空间该文件。
    $ git checkout <branch> -- <file>
    
    # 用某个提交(commit_id)目录树指定文件替换工作空间该文件。
    $ git checkout commit_id -- <file>
    
  15. diff:显示WorkSpace中的文件和暂存区文件的差异,会显示文件内容的差异

    # 比较工作空间和暂存区
    $ git diff [file]
    
    # 比较两个提交对象的差异
    $ git diff <commit_id1> <commit_id2>
    
  16. ls-files:查看文件列表

    # 查看所有缓存的文件
    $ git ls-files
    
    # 查看所有未被跟踪的文件,包括.gitignore的文件
    $ git ls-files -o
    
    # 查看modified状态的文件
    $ git ls-files -modified
    
    # 查看暂存区的文件详细信息
    $ git ls-files -s
    

4.5 文件操作命令示意图

在这里插入图片描述

5 git分支

5.1 分支概念

Git 的分支模型是它的“必杀技特性”,也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。git官网有一句介绍:Git 保存的不是文件的变化或者差异,而是一系列不同时刻的文件快照。这也正是git实现分支模型及分布式版本控制的基石。

Git 分支,本质上仅仅是指向提交对象的可变指针。创建分支时就是在当前的提交上创建了一个新的可移动的指针。然后git有一个特殊的指针:HEAD,指向当前所在的本地分支。每一个分支指向一个提交对象。HEAD指针指向当前本地分支。我们所说的本地仓库,实际上就是HEAD指针指向的本地分支所指向的提交对象。

由于 Git 的分支实质上仅是包含所指提交对象校验和(长度为 40 的 SHA-1 值字符串)的文件,所以它的创建和销毁都异常高效。

5.2 分支操作

  1. 新建testing分支

    git branch testing
    

    在这里插入图片描述


  1. 切换到testing分支

    git checkout testing  
    

    在这里插入图片描述

​ 此时master分支和testing分支指向同一个提交,所以工作空间看起来并没有变化。接下来修改工作空间文件,然后提交。

  1. 使用testing分支提交

    #修改文件后
    git commit -a -m testing分支提交
    

    在这里插入图片描述

    此时testing分支指针向新的提交对象前进,master分支还是指向原来的提交对象。

  2. 切回到master分支

    git checkout master
    

    在这里插入图片描述

    此时工作空间的文件会变为master所指向的提交对象的状态。

  3. master分支提交

    # 修改文件后
    git commit -a -m master分支提交
    

    在这里插入图片描述

    此时分支出现分叉,使用git log --graph命令可以图形化(字符图形)查看分支提交历史。

  4. 分支合并

    #当前分支为master
    git merge testing
    

    合并之后会将testing分支指向的commit object的修改内容添加到master指向的commit object,并生成一次新的提交。然后就可以删除被合并的testing分支。

  5. 删除分支

    git branch -d testing
    
  6. 发生冲突的合并

    如果合并的两个分支都修改了同一份文件,git将无法成功完成合并生成一个新的提交,此时Git 会暂停下来,等待你去解决合并产生的冲突。分支状态变为合并中,冲突文件状态变为both modified。冲突将在下一节具体复现。

  7. 其他分支操作

    # 查看所有本地分支
    $ git branch
    
    # 查看所有远程分支
    $ git branch -r
    
    # 查看所有本地和远程分支
    $ git branch -a
    
    # 新建分支并将其指向某个提交对象
    $ git branch [branch] [commit_id]
    
    # 新建一个分支,与指定的远程分支建立追踪关系
    $ $ git branch --track [branch] [remote-branch]
    
    # 删除本地分支,-D表示强制删除
    $ git branch -d [branch] 
    
    # 查看所有本地分支
    $ git branch
    
    # 删除远程分支,remote表示远程主机名,默认origin
    $ git push origin --delete [branch-name]
    $ git branch -dr [remote/branch]
    

5.3 合并冲突解决方案

前面说到如果合并的两个分支都修改了同一份文件,合并会产生冲突。具体情景:

创建test1分支,在test1分支修改testconflict.txt文件并提交:

在这里插入图片描述

切换到master分支,master分支也修改testconflict.txt文件并提交,

然后合并master分支和test1分支,发生冲突

在这里插入图片描述

查看冲突文件,发现git有记录冲突内容的格式。冲突文件状态为both modified,且分支状态为master|MERGING。解决冲突的方式是手动修改文件改正冲突内容后重新提交

在这里插入图片描述

重新提交。分支状态变为正常的master

在这里插入图片描述


git的分支是分布式版本控制的核心概念,功能强大,也比较难以理解。可以查看官网资料学习,https://git-scm.com/book/en/v2

6 总结

作为一套内容寻址文件系统,Git 不仅仅是一个版本控制系统,它同时是一个非常强大且易用的工具。git已经是开发人员必备技能,也是世界上最先进的分布式版本控制系统,许多公司普遍使用基于git的代码托管网站。有名的代码托管网站有github、gitlab、bitbucket、gitee(码云)。各种git图形化工具也是层出不穷,eclipse、idea等IDE软件也都集成了git插件,但是使用图形化工具的同时,也必须理解git命令及git版本控制原理。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值