• 集中式版本控制系统
    • 版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
    • 集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊
  • 分布式版本控制系统
    • 分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了
    • 和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了
    • 在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
  • CVS作为最早的开源而且免费的集中式版本控制系统,直到现在还有不少人在用。由于CVS自身设计的问题,会造成提交文件不完整,版本库莫名其妙损坏的情况。同样是开源而且免费的SVN修正了CVS的一些稳定性问题,是目前用得最多的集中式版本库控制系统
  • 创建版本库

    版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

  • 具体教程可以从廖雪峰网站-Git简介-创建版本库
  • 所有的版本控制系统,其实只能跟踪文本文件的改动。不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,前面我们举的例子只是为了演示,如果要真正使用版本控制系统,就要以纯文本方式编写文件。
  • 千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等,都是由记事本的弱智行为带来的。建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可
  • 创建本地版本库

    //进入learngit
    git init
    
  • 关联远程仓库

    git remote add origin git@github.com:owenr/repository.git //origin:给仓库起名,后面是ssh地址,可在github仓库点击clone or dowmload获取
    
  • 解除关联

    git remote rm origin //origin是远程仓库在本地git中的名称
    
  • 新建文件

    touch filename //新建文件
    vi filename //新建文件并编辑(文件已存在则直接编辑)
    
  • 上传文件到仓库步骤(网站讲解章节:时光机穿梭)
  1. 编写文件(文本文件,不能是图片之类二进制文件)比如readme.txt
  2. 保存到仓库下(比如learngit)
  3. 告诉git你保存了这么个东西到仓库里面了:
    1. 在learngit文件夹里右键git bash here
    2. 在git bash here里面git add file,
      也就是说git add file的这个file必须是learngit里面有的
  4. 修改了文件并保存之后,用git diff readme.txt查看修改细节:
  • git log只能查看commit的历史
  • 执行git log 命令无法退出,按q退出历史记录列表即可重新输入其他命令

  • 版本回退也可以是git reset –hard head(后面跟几个^)回到历史版本,前提是记得目标版本是要加几个^

  • 撤销修改
    其实有点类似于版本回退,只是版本回退是已经提交之后回退到分支里某个历史版本,而撤销修改是把工作区恢复到和版本库相同。

有时你git add之后又在工作区对文件进行了多次修改(但是都没有git add),这时执行git checkout – file就可以撤销在工作区做的所有修改

  • 工作区和暂存区
  • git diff的比较
  • 删除文件
  1. 新建一个文件并add+commit到版本库的分支里面
  2. 要删除的话,先将文件从工作区手动删除或rm file用命令行删除;这样,文件就从工作区被删除,但是版本库中还是有该文件
  3. 发现删错了,git checkout – file,撤销修改(这里是撤销删除操作)
  4. 要连版本库都删除的话,git rm file+commit;删错还可以版本回退,但是会丢失最近一次commit后的修改
  • cat file查看的是工作区或暂存区最新的版本
  • 关联远程仓库
    • 仓库最好同名,同名可以直接git push
    • 一个本地仓库最好只关联一个远程仓库,不然同时向两个仓库push有难度
  • 新建分支

git checkout 分支名(新建并切换到一个分支)

创建分支

  1. 创建并切换到新分支:git checkout -b 分支名称
  2. 之后add、commit等所有操作都是保存在新分支中的
  3. 未合并分支前切换回主分支的话,查看在新建分支修改过的文件,它仍然是未修改的模样,因为修改这个操作是在其他分支上,而且还为合并。
  4. 合并分支:git merge 其他分支
  5. 切换分支:git checkout 其他分支,切换到其他分支,切换后电脑上的文件也会跟着变成所在分支的样子
  6. 删除分支:git branch -d 分支

    合并冲突

  • 两个分支都对同一个(注意是同一个)文件进行了修改,合并的时候就会出现冲突
  • 解决冲突:手动修改文件(也就是选择保留一种修改),再提交,然后就可以合并了
  • 出现冲突的文件片段:

    <<<<<<< HEAD
    public ModelAndView record1(@RequestParam("model")String model){
    =======
    public ModelAndView record1(@RequestParam("editor")String editor,
                                @RequestParam("model")String model,
                                @RequestParam("year")String year1){
        int year=Integer.parseInt(year1);
    >>>>>>> add_year
    
  • 冲突标记<<<<<<< (7个<)与=======之间的内容是我的修改;
    =======与>>>>>>>之间的内容是别人的修改
  • 修改完之后,git status会发现有未提交的修改,提交即大功告成

    git commit -m "……"
    
  • 用git log可以看到分支合并图

克隆远程仓库

  • 在一个合适的目录下(不用新建文件夹,clone项目后会自动生成一个以项目名命名的文件夹来存放该项目):git clone git@github.com:Eliyser/仓库.git
  • 目前无法实现只复制指定目录的git功能。
  • 不用再关联,直接git push -u origin master就把本地做的修改推送上去了(首次推需要-u)

    pull request

  • 从别人那里fork来的仓库里点pull request,然后一路按按钮就可以请求把自己的仓库合并到别人的仓库里了,别人的仓库会自动提示主人我修改了什么东西,合并的时候也只合并修改的部分

    补充一个从创建版本库到push项目全过程

    创建版本库

  • 手动或利用一下git命令创建一个新的文件夹,如learngit

    mkdir learngit
    cd learngit
    
  • 新建的文件夹里只有feature分支
  • 进入该文件夹后,将其变为版本库

    git init
    
  • git init之后只有master分支

    克隆项目进来

  • 在learngit里面

    git clone url
    
  • 一般这个url都是自己的github仓库,然后这个github仓库一般是从别人(老大)的仓库fork来的,相信我,没人会直接让你动他的源仓库的!而且直接从别人的仓库clone项目下来,到最后开发完要把代码合并上去的时候,你没有人家的公钥,根本合并不上去,你开发了等于没开发。所以还是乖乖fork源仓库,clone项目下来,开发完合并回去,再pull request到源仓库等待审核吧。PS:pull request只能发起一次,而且只能在有fork关系的仓库之间发起

    开发

  • 创建并切换到新分支上,如add_year

    git checkout -b add_year
    
  • 可以每天关机前将改动add、commit到该分支
  • 查看所有分支的话

    git branch
    
  • 开发完成后,切换回主分支,下来远程分支到master上

    git checkout master
    git pull(结果是Already up-to-date) //和源仓库同步(可能出现合并冲突,如果合并功能分支的冲突可能较少的话建议先合并功能分支),未添加源仓库为本地远程仓库见“本地仓库同步到远程仓库”步骤
    
  • 本地仓库同步到源仓库

    • 先查询本地远程仓库

    • 添加源仓库

    • 再查看远程仓库目录

    • 下面这三步相当于git pull upstream master

      • 抓取源仓库的修改文件(应该可以指定分支,不指定的话抓取全部分支)

        git fecth upstream master

      • 切换到另一个要同步的分支,比如master

        git checkout master
        
      • 合并修改

      • 放心吧,合并完了自己写的东西还在
    • 此时本地仓库和源仓库已同步,但是远程仓库尚未同步,要同步需将master分支git push到远程仓库
  • 合并分支,有冲突的话就把冲突文件改改

    git merge add_year(结果是Fast-forward,有的时候好像up-to-date还是什么的也是对的,可以到github上查看master分支看文件是否已更新)
    
  • 改完了再commit
  • 推送到远程仓库

    git push origin master
    
  • 删除add_year分支

    git branch -d add_year
    

    git常用命令

  • 详细开发流程可以参见笔记:git协同开发

    异常

  • git push后出现rejected non-fast-forward错误
  • 括号里也可能是你的commit信息,总之这些都表示git仓库中已经有一部分代码(好像readme.txt也算),所以它不允许你直接把你的代码覆盖上去。于是你有两种选择:
  • 强制覆盖(有的时候真的不知道到底为什么就是push不上去就直接强推了):

    git push -f origin master 
    
  • 先把git的东西fetch到本地来merge后再push

    git fetch 
    git merge
    //等价于
    git pull
    
  • 上面这三行代码应该还会报错:你没有指定仓库和分支,那么我们可以指定默认的仓库和分支

    git config branch.master.remote origin
    git config branch.master.merge refs/heads/master
    

    .gitignore

  • 需要忽略什么文件都可以写到这个文件里面,这个文件用编辑器都建不出来,只能在Git Bash里建,建在根目录或者和src包同级都可以
  • 格式:

    # 忽略的文件夹
    target
    out 
    # 忽略的文件,前面加!的话表示不要忽略
    *.idea
    *.iml
    
  • 如果忽略规则创建于代码提交之后,那么不会影响到已经提交的文件,需要删除的话执行以下命令
  1. 把远程项目拉下来 git pull
  2. 查看文件夹 dir
  3. 删除文件(夹)git rm -r –cached filename //cached应该是只删除远程库不删除本地库的意思
  4. 提交修改 git commit
  5. 推到远程库 git push
  • 以上操作要在与远程库分支名相同的分支下操作,如过要删除develop分支下的文件夹,却在本地feature分支做了以上操作,那么要merge到develop分支并由它push。
  • 参考文章
  • 不然就把文件先搬到别的地方,加好忽略规则之后push一遍,最后把文件搬回来,这样本地的某些文件就不会出现在远程了。