设为首页 收藏本站
查看: 725|回复: 0

[经验分享] Git与Repo入门

[复制链接]

尚未签到

发表于 2018-9-17 09:52:58 | 显示全部楼层 |阅读模式
Git与Repo入门
版本控制
  版本控制是什么已不用在说了,就是记录我们对文件、目录或工程等的修改历史,方便查看更改历史,备份以便恢复以前的版本,多人协作。。。
一、原始版本控制
  最原始的版本控制是纯手工的版本控制:修改文件,保存文件副本。有时候偷懒省事,保存副本时命名比较随意,时间长了就不知道哪个是新的,哪个是
老的了,即使知道新旧,可能也不知道每个版本是什么内容,相对上一版作了什么修改了,当几个版本过去后,很可能就是下面的样子了:

二、本地版本控制
  手工管理比较麻烦且混乱,所以出现了本地版本控制系统,记录文件每次的更新,可以对每个版本做一个快照,或是记录补丁文件。比如RCS。

三、集中版本控制
  但是本地版本控制系统偏向于个人使用,或者多个使用的人必须要使用相同的设备,如果需要多人协作就不好办了,于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生,比如Subversion,Perforce。
  在CVCS中,所有的版本数据都保存在服务器上,一起工作的人从服务器上同步更新或上传自己的修改。

  但是,所有的版本数据都存在服务器上,用户的本地设备就只有自己以前所同步的版本,如果不连网的话,用户就看不到历史版本,也无法切换版本验证问题,或在不同分支工作。。
  而且,所有数据都保存在单一的服务器上,有很大的风险这个服务器会损坏,这样就会丢失所有的数据,当然可以定期备份。
四、分布式版本控制
  针对CVCS的以上缺点,出现了分布式版本控制系统( Distributed Version Control System,简称 DVCS ),如GIT,Mercurial。
  DVCS不是复制指定版本的快照,而是把所有的版本信息仓库全部同步到本地,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连
网时push到相应的服务器或其他用户那里。由于每个用户那里保存的都是所有的版本数据,所以,只要有一个用户的设备没有问题就可以恢复所有的数据。
  当然,这增加了本地存储空间的占用。

GIT
  必须要了解GIT的原理,才能知道每个操作的意义是什么,才能更容易地理解在什么情况下用什么操作,而不是死记命令。当然,第一步是要获得一个GIT仓库。
一、获得GIT仓库
  有两种获得GIT仓库的方法,一是在需要用GIT管理的项目的根目录执行:
  git init
  执行后可以看到,仅仅在项目目录多出了一个.git目录,关于版本等的所有信息都在这个目录里面。
  另一种方式是克隆远程目录,由于是将远程服务器上的仓库完全镜像一份至本地,而不是取某一个特定版本,所以用clone而不是checkout:
  git clone
二、GIT中版本的保存
  记录版本信息的方式主要有两种:

  •   记录文件每个版本的快照
  •   记录文件每个版本之间的差异
  GIT采用第一种方式。像Subversion和Perforce等版本控制系统都是记录文件每个版本之间的差异,这就需要对比文件两版本之间
的具体差异,但是GIT不关心文件两个版本之间的具体差别,而是关心文件的整体是否有改变,若文件被改变,在添加提交时就生成文件新版本的快照,而判断文
件整体是否改变的方法就是用SHA-1算法计算文件的校验和。
  GIT能正常工作完全信赖于这种SHA-1校验和,当一个文件的某一个版本被记录之后会生成这个版本的一个快照,但是一样要能引用到这个快照,GIT中对快照的引用,对每个版本的记录标识全是通过SHA-1校验和来实现的。
  当一个文件被改变时,它的校验和一定会被改变(理论上存在两个文件校验和相同,但机率小到可以忽略不计),GIT就以此判断文件是否被修改,及以些记录不同版本。
  在工作目录的文件可以处于不同的状态,比如说新添加了一个文件,GIT发觉了这个文件,但这个文件是否要纳入GIT的版本控制还是要由我们自己决定,比如编译生成的中间文件,我们肯定不想纳入版本控制。下面就来看下文件状态。
三、GIT文件操作
  版本控制就是对文件的版本控制,对于Linux来说,设备,目录等全是文件,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。
文件状态
  GIT仓库所在的目录称为工作目录,这个很好理解,我们的工程就在这里,工作时也是在这里做修改。
  在工作目录中的文件被分为两种状态,一种是已跟踪状态(tracked),另一种是未跟踪状态(untracked)。只有处于已跟踪状态的文件才被纳入GIT的版本控制。如下图:

  当我们往工作目录添加一个文件的时候,这个文件默认是未跟踪状态的,我们肯定不希望编译生成的一大堆临时文件默认被跟踪还要我们每次手动将这些文件清除出去。用以下命令可以跟踪文件:
  git add
  上图中右边3个状态都是已跟踪状态,其中的灰色箭头只表示untrackedtracked的转换而不是
untrackedunmodified的转换,新添加的文件肯定算是被修改过的。那么,staged状态又是什么呢?这就要搞清楚
GIT的三个工作区域:本地数据(仓库)目录,工作目录,暂存区,如下图所示:

  git directory就是我们的本地仓库.git目录,里面保存了所有的版本信息等内容。
  working driectory,工作目录,就是我们的工作目录,其中包括未跟踪文件及已跟踪文件,而已跟踪文件都是从git directory取出来的文件的某一个版本或新跟踪的文件。
  staging area,暂存区,不对应一个具体目录,其时只是git directory中的一个特殊文件。
  当我们修改了一些文件后,要将其放入暂存区然后才能提交,每次提交时其实都是提交暂存区的文件到git仓库,然后清除暂存区。而checkout某一版本时,这一版本的文件就从git仓库取出来放到了我们的工作目录。
文件状态的查看
  那么,我们怎么知道当前工作目录的状态呢?哪些文件已被暂存?有哪些未跟踪的文件?哪些文件被修改了?所有这些只需要一个命令,git status,如下图所示:

  GIT在这一点做得很好,在输出每个文件状态的同时还说明了怎么操作,像上图就有怎么暂存、怎么跟踪文件、怎么取消暂存的说明。
文件暂存
  在上图中我们可以很清楚地看到,filea未跟踪,fileb已被暂存(changes to be
committed),但是怎么还有一个fileb是modified但unstaged呢?这是因为当我们暂存一从此文件时,暂存的是那一文件当时的版
本,当暂存后再次修改了这个文件后就会提示这个文件暂存后的修改是未被暂存的。
  接下来我们就看怎么暂存文件,其实也很简单,从上图中可以看到GIT已经提示我们了:use "git add ..." to update what will be committed,通过
  git add ...
  就可以暂存文件,跟踪文件同样是这一个命令。在这个命令中可以使用glob模式匹配,比如"file[ab]",也可以使用"git add ."添加当前目录下的所有文件。
  取消暂存文件是
  git reset HEAD ...
  若修改了一个文件想还原修改可用
  git checkout -- ...
查看文件修改后的差异
  当我们修改过一些文件之后,我们可能想查看我们都修改了什么东西,用"git status"只能查看对哪些文件做了改动,如果要看改动了什么,可以用:
  git diff
  比如下图:

  ---a表示修改之前的文件,+++b表示修改后的文件,上图表示在fileb的第一行后添加了一行"bb",原来文件的第一行扩展为了修改后的1、2行。
  但是,前面我们明明用"git status"看到filesb做了一些修改后暂存了,然后又修改了fileb,理应有两次修改的,怎么只有一个?
  因为"git diff"显示的是文件修改后还没有暂存起来的内容,那如果要比较暂存区的文件与之前已经提交过的文件呢,毕竟实际提交的是暂存区的内容,可以用以下命令:

  /dev/null表示之前没有提交过这一个文件,这是将是第一次提交,用:
  git diff --staged
  是等效的,但GIT的版本要大于1.6.1。
  再次执行"git add"将覆盖暂存区的内容。
忽略一些文件
  如果有一些部件我们不想纳入版本控制,也不想在每次"git status"时看到这些文件的提示,或者很多时候我们为了方便会使用"git add ."添加所有修改的文件,这时就会添加上一些我们不想添加的文件,怎么忽略这些文件呢?
  GIT当然提供了方法,只需在主目录下建立".gitignore"文件,此文件有如下规则:

  •   所有以#开头的行会被忽略
  •   可以使用glob模式匹配
  •   匹配模式后跟反斜杠(/)表示要忽略的是目录
  •   如果不要忽略某模式的文件在模式前加"!"
  比如:
  # 此为注释 – 将被 Git 忽略
  *.a # 忽略所有 .a 结尾的文件
  !lib.a # 但 lib.a 除外
  /TODO # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
  build/ # 忽略 build/ 目录下的所有文件
  doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
移除文件
  当我们要删除一个文件时,我们可能就直接用GUI删除或者直接rm [file]了,但是看图:

  我们需要将文件添加到暂存区才能提交,而移除文件后是无法添加到暂存区的,那么怎么移除一个文件让GIT不再将其纳入版本控制呢?上图中GIT已经给出了说明:
  git rm ...
  执行以上命令后提交就可以了,有时我们只是想将一些文件从版本控制中剔除出去,但仍保留这些文件在工作目录中,比如我们一不小心将编译生成的中
间文件纳入了版本控制,想将其从版本控制中剔除出去但在工作目录中保留这些文件(不然再次编译可要花费更多时间了),这时只需要添加"--cached"
参数。
  如果我们之前不是通过"git rm"删除了很多文件呢?比如说通过patch或者通过GUI,如果这些文件命名没有规则,一个一个地执行"git rm"会搞死人的,这时可以用以下命令:

移动文件
  和移除文件一样,移动文件不可以通过GUI直接重命令或用"mv"命令,而是要用"git mv",不然同移除文件一样你会得到如下结果:

  如果要重命名文件可以使用
  git mv old_name new_name
  这个命令等效于
  mv old_name new_name
  git rm old_name
  git add new_name
交互式暂存
  使用git add -i可以开启交互式暂存,如图所示,系统会列出一个功能菜单让选择将要执行的操作。

移除所有未跟踪文件
  git clean [options]  一般会加上参数-df,-d表示包含目录,-f表示强制清除。
储藏-Stashing
  可能会遇到这样的情况,你正在一个分支上进行一个特性的开发,或者一个Bug的修正,但是这时突然有其他的事情急需处理,这时该怎么办?不可能
就在这个工作进行到一半的分支上一起处理,先把修改的Copy出去?太麻烦了。这种情况下就要用到Stashing了。假如我们现在的工作目录是这样子的
$ git status  
# On branch master
  
# Changes to be committed:
  
#
  
(use "git reset HEAD ..." to unstage)
  
#
  
#
  
modified:
  
index.html
  
#
  
# Changed but not updated:
  
#
  
(use "git add ..." to update what will be committed)
  
#
  
#
  
modified:
  
lib/simplegit.rb
  此时如果想切换分支就可以执行以下命令
$ git stash  
Saved working directory and index state \"WIP on master: 049d078 added the index file"HEAD is now at 049d078 added the index file(To restore them type "git stash apply")
  这时你会发现你的工作目录变得很干净了,就可以随意切分支进行其他事情的处理了。
  我们可能不只一次进行"git stash",通过以下命令可以查看所有stash列表
$ git stash list  
stash@{0}: WIP on master: 049d078 added the index filestash@{1}: WIP on master: c264051... Revert "added file_size"
  当紧急事情处理完了,需要重新回来这里进行原来的工作时,只需把Stash区域的内容取出来应用到当前工作目录就行,命令就是
git stash apply
  如果不基参数就应用最新的stash,或者可以指定stash的名字,如:stash@{1},可能通过
git stash show
  显示stash的内容具体是什么,同git stash apply一样,可以选择指定stash的名字。
  git stash apply之后再git stash list会发现,apply后的stash还在stash列表中,如果要将其从stash列表中删除可以用
git stash drop
  丢弃这个stash,stash的命令参数都可选择指定stash名字,否则就是最新的stash。
  一般情况下apply stash后应该就可以把它从stash列表删除了,先apply再drop还是比较繁琐的,使用以下一条命令就可以同时完成这两个操作
git stash pop
  如果我们执行git stash时工作目录的状态是部分文件已经加入了暂存区,部分文件没有,当我们执行git stash apply之后会发现所有文件都变成了未暂存的,如果想维持原来的样子操持原来暂存的文件仍然是暂存状态,可以加上--index参数
git stash apply --index
  还有这么一种情况,我们把原来的修改stash了,然后修复了其他一些东西并进行了提交,但是,这些提交的文件有些在之前已经被stash了,
那么git stash apply时就很可能会遇到冲突,这种情况下就可以在stash时所以提交的基础上新建一个分支,然后再apply
stash,当然,这两个步骤有一人简单的完成方法
git stash branch
四、提交与历史
  了解了文件的状态,我们对文件进行了必要的修改后,就要把我们所做的修改放入版本库了,这样以后我们就可以在需要的时候恢复到现在的版本,而要恢复到某一版,一般需要查看版本的历史。
提交
  提交很简单,直接执行"git commit"。执行git
commit后会调用默认的或我们设置的编译器要我们填写提示说明,但是提交说明最好按GIT要求填写:第一行填简单说明,隔一行填写详细说明。因为第一
行在一些情况下会被提取使用,比如查看简短提交历史或向别人提交补丁,所以字符数不应太多,40为好。下面看一下查看提交历史。
查看提交历史
  查看提交历史使用如下图的命令

  如图所示,显示了作者,作者邮箱,提交说明与提交时间,"git log"可以使用放多参数,比如:

  仅显示最新的1个log,用"-n"表示。

  显示简单的SHA-1值与简单提交说明,oneline仅显示提交说明的第一行,所以第一行说明最好简单点方便在一行显示。
  "git log --graph"以图形化的方式显示提交历史的关系,这就可以方便地查看提交历史的分支信息,当然是控制台用字符画出来的图形。
  "git log"的更多参数可以查看命令帮助。
不经过暂存的提交
  如果我们想跳过暂存区直接提交修改的文件,可以使用"-a"参数,但要慎重,别一不小心提交了不想提交的文件
  git commit -a
  如果需要快捷地填写提交说明可使用"-m"参数
  git commit -m 'commit message'
修订提交
  如果我们提交过后发现有个文件改错了,或者只是想修改提交说明,这时可以对相应文件做出修改,将修改过的文件通过"git add"添加到暂存区,然后执行以下命令:
  git commit --amend
  然后修改提交说明覆盖上次提交,但只能重写最后一次提交。
重排提交
  通过衍合(rebase)可以修改多个提交的说明,并可以重排提交历史,拆分、合并提交,关于rebase在讲到分支时再说,这里先看一下重排提交。
  假设我们的提交历史是这样的:

  如果我们想重排最后两个提交的提交历史,可以借助交互式rebase命令:
  git rebase -i HEAD~2 或 git rebase -i 3366e1123010e7d67620ff86040a061ae76de0c8

  HEAD~2表示倒数第三个提交,这条命令要指定要重排的最旧的提交的父提交,此处要重排Second commit与Third commit,所以要指定Initial commit的Commit>

  注释部分详细说明了每个选项的作用,如果我们想交互这两个提交,只需把开头的这两行交换下位置就OK了,交换位置后保存,然后看下提交历史:


  可以看到提交历史已经变了,而且最新的两个提交的Commit>删除提交与修改提交说明
  如果要删除某个提交,只需要删除相应的行就可以了,而要修改某个提交的提交说明的话,只需要把相应行的pick改为reward。
合并提交-squashing
  合并提交也很简单,从注释中的说明看,只需要把相应的行的pick改为squash就可以把这个提交全并到它上一行的提交中。
拆分提交
  至于拆分提交,由于Git不可能知道你要做哪里把某一提交拆分开,把以我们就需要让Git在需要拆分的提交处停下来,由我们手动修改提交,这时要把pick改为edit,这样Git在处理到这个提交时会停下来,此时我们就可以进行相应的修改并多次提交来拆分提交。
撤销提交
  前面说了删除提交的方法,但是如果是多人合作的话,如果某个提交已经Push到远程仓库,是不可以用那种方法删除提交的,这时就要撤销提交
  git revert
  这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。
Reset
  git reset会修改HEAD到指定的状态,用法为
  git reset [options]
  这条命令会使HEAD提向指定的Commit,一般会用到3个参数,这3个参数会影响到工作区与暂存区中的修改:

  •   --soft: 只改变HEAD的State,不更改工作区与暂存区的内容
  •   --mixed(默认): 撤销暂存区的修改,暂存区的修改会转移到工作区
  •   --hard: 撤销工作区与暂存区的修改
cherry-pick
  当与别人和作开发时,会向别人贡献代码或者接收别人贡献的代码,有时候可能不想完全Merge别人贡献的代码,只想要其中的某一个提交,这时就可以使用cherry-pick了。就一个命令
  git cherry-pick
filter-branch
  这条命令可以修改整个历史,如从所有历史中删除某个文件相关的信息,全局性地更换电子邮件地址。
五、GIT分支
  分支被称之为GIT最强大的特性,因为它非常地轻量级,如果用Perforce等工具应该知道,创建分支就是克隆原目录的一个完整副本,对于
大型工程来说,太费时费力了,而对于GIT来说,可以在瞬间生成一个新的分支,无论工程的规模有多大,因为GIT的分支其实就是一指针而已。在了解GIT
分支之前,应该先了解GIT是如何存储数据的。
  前面说过,GIT存储的不是文件各个版本的差异,而是文件的每一个版本存储一个快照对象,然后通过SHA-1索引,不只是文件,包换每个提交都是一个对象并通过SHA-1索引。无论是文本文件,二进制文件还是提交,都是GIT对象。
GIT对象
  每个对象(object) 包括三个部分:类型大小内容。大小就是指内容的大小,内容取决于对象的类型,有四种类型的对象:"blob"、"tree"、 "commit" 和"tag"。

  •   “blob”用来存储文件数据,通常是一个文件。
  •   “tree”有点像一个目录,它管理一些“tree”或是 “blob”(就像文件和子目录)
  •   一个“commit”指向一个"tree",它用来标记项目某一个特定时间点的状态。它包括一些关于时间点的元数据,如提交时间、提交说明、作者、提交者、指向上次提交(commits)的指针等等。
  •   一个“tag”是来标记某一个提交(commit) 的方法。
  比如说我们执行了以下代码进行了一次提交:
  $ git add README test.rb LICENSE2
  $ git commit -m 'initial commit of my project'
  现在,Git 仓库中有五个对象:三个表示文件快照内容的 blob 对象;一个记录着目录树内容及其中各个文件对应 blob 对象索引的
tree 对象;以及一个包含指向 tree 对象(根目录)的索引和其他提交信息元数据的 commit
对象。概念上来说,仓库中的各个对象保存的数据和相互关系看起来如下图:

  如果进行多次提交,仓库的历史会像这样:

分支引用
  所谓的GIT分支,其实就是一个指向某一个Commit对象的指针,像下面这样,有两个分支,master与testing:

  而我们怎么知道当前在哪一个分支呢?其实就是很简单地使用了一个名叫HEAD的指针,如上图所示。HEAD指针的值可以为一个SHA-1值或是一个引用,看以下例子:

  git的所有版本信息都保存了Working
Directory下的.git目录,而HEAD指针就保存在.git目录下,如上图所有,目前为止已经有3个提交,通过查看HEAD的值可以看到我们当
前在master分支:refs/heads/master,当我们通过git
checkout取出某一特定提交后,HEAD的值就是成了我们checkout的提交的SHA-1值。
  记录我们当前的位置很简单,就是能过HEAD指针,HEAD指向某一提交的SHA-1值或是某一分支的引用。
新建分支
  git branch
  有时需要在新建分支后直接切换到新建的分支,可以直接用checkout的-b选项
  git checkout -b
删除分支
  git branch -d
  如果在指定的分支有一些unmerged的提交,删除分支会失败,这里可以使用-D参数强制删除分支。
  git branch -D
检出分支或提交
  检出某一分支或某一提交是同一个命令
  git checkout  |
分支合并(merge)
  当我们新建一个分支进行开发,并提交了几次更新后,感觉是时候将这个分支的内容合回主线了,这是就可以取出主线分支,然后把分支的更新merge回来:
  git checkout master
  git merge testing
  如果master分支是testing分支的直接上游,即从master延着testing分支的提交历史往前走可以直接走到testing分支的最新提交,那么系统什么也不需要做,只需要改变master分支的指针即可,这被称之为"Fast Forward"。
  但是,一般情况是这样的,你取出了最新的master分支,比如说master分支最新的提交是C2(假设共3次提交C0

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-588127-1-1.html 上篇帖子: 在windows上,Git-2.9.3-rebase-i-64-bit安装和初始化 下篇帖子: gitolite配置git服务器权限
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表