Git学习

Git

分布式的版本控制系统。

笔记来源于廖雪峰老师Git教程:
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

Git原理

Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。

名词解释

这里写图片描述

  • 工作区

    就是你在你的电脑里能看到的目录,比如创建的learngit文件夹。

  • 版本库

    工作区中有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

    版本库中分为stage(暂存区),还有Git为我们创建的第一个分支master,以及指向master的一个指针HEAD.

  • 分支

    创建一个属于自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

    Git为我们创建第一个分支master,为主分支。

    HEAD指针指向当前分支。

创建版本库

版本库又名仓库,可以简单理解为一个仓库,这个目录里的所有文件可以被Git管理起来。

创建版本库:

$ mkdir learngit    // 创建一个空目录   
$ cd learngit
$ git init       // 通过git init命令把这个目录变成Git可以管理的仓库

此时当前目录下多了一个.git的隐藏目录,是Git用来跟踪管理版本库的(没事不要手动修改)。

添加文件到Git仓库,分两步:

$ git add <file>        //  添加工作区的文件至暂存区  
$ git commit -m "log"   //  把暂存区的所有内容提交到当前分支

时光机穿梭

一些常用命令:

$ git status    // 显示仓库当前的状态

$ git diff <file>   // 如果git status告诉你文件有修改过,那么使用该命令显示file具体修改的内容

$ git log   // 显示从最近到最远的提交日志

$ git log --pretty=oneline    // 让信息整齐显示的命令
// 命令显示格式: commit_id log

$ git reflog  // 记录你的每一次命令

$ cat readme.txt   // 查看版本内容

版本回退

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交。上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

当回退版本时,Git仅仅是把HEAD指向改变,然后顺便把工作区的文件更新了。

则版本回退命令为:

$ git reset --hard HEAD^  // 回退到上一个版本
$ git reset --hard HEAD~100  // 回退到上第100个版本
$ git reset --hard 3628164   // 回退到指定id的commit 

要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
再使用版本回退命令。

撤销修改

丢弃工作区的修改:

$ git checkout -- file

有两种情况:

一种是文件自修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的状态;

一种是文件已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

把暂存区的修改撤销掉:

$ git reset HEAD file
撤销情景
  • 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时

    $ git checkout -- file
    
  • 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改

    $ git reset HEAD file    // 先把暂存区的修改撤销掉
    $ git checkout -- file   // 再丢弃工作区的修改
    
  • 已经提交了不合适的修改到版本库时,想要撤销本次提交(前提是没有推送到远程库)

    $ git reset --hard HEAD^  // 版本回退
    

删除文件

在工作区删除文件后,工作区和版本库不一致。
此时有两种情况:

  • 确定要从版本库删除文件

    $ git rm file
    $ git commit -m "log"
    
  • 误删,要恢复工作区文件

    $ git checkout -- file
    
    // git checkout 是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
    

远程仓库

Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。

最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。

先在GitHub上创建远程仓库,此时在GitHub上的这个仓库是空的。现在有两个选择:

  • 可以把一个已有的本地仓库与之关联(先有本地库,后有远程库)

  • 可以从这个仓库克隆出新的仓库(先有远程库,后有本地库)

然后,把本地仓库的内容推送到GitHub仓库。

添加远程库

先有本地库,后有远程库的时候,如何关联远程库。

现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。

在本地的仓库下运行命令:

$ git remote add origin git@server-name:path/repo-name.git
$ git remote add origin git@github.com:YangZhaobin/learngit.git

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的。

下一步,就可以把本地库的所有内容推送到远程库上:

$ git push -u origin master

把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

从现在起,只要本地作了提交,就可以通过命令把本地master分支的最新修改推送至GitHub:

$ git push origin master

从远程库克隆

先有远程库,后有本地库的时候,如何关联远程库。

克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆:

$ git clone git@github.com:YangZhaobin/learngit.git

分支管理

创建和合并分支

每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。

创建 + 切换分支:

$ git checkout -b <name>

相当于以下两条命令:

$ git branch <name>  // 创建分支
$ git checkout <name>  // 切换分支

查看当前所有分支:

$ git branch
* dev    // 当前分支前面会标一个*号
  master

合并某分支到当前分支:

$ git checkout master  // 先切换回master分支
$ git merge <name>  // 合并指定分支到当前分支

删除指定分支:

$ git branch -d <name>

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

在合并时禁用Fast forward模式,--no-ff参数,表示禁用Fast forward

$ git merge --no-ff -m "merge with no-ff" dev

合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。

使用fast forward合并后为:
这里写图片描述

不使用fast forward合并后为:
这里写图片描述

解决冲突

master分支和feature分支各自都分别有新的提交时,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突。

当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。

带参数的git log也可以看到分支的合并情况(分支合并图):

$ git log --graph --pretty=oneline --abbrev-commit

分支管理策略

在实际开发中,我们应该按照几个基本原则进行分支管理:

  • master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

  • 干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

  • 每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了

BUG分支

由于分支的强大,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

Git提供一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

$ git stash

在修复完成之后工作区是干净的,用git stash list命令看看:

$ git stash list
stash@{0}: WIP on dev: 6224937 add merge

工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:

一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;

另一种方式是用git stash pop,恢复的同时把stash内容也删了。

恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:

$ git stash apply stash@{0}

总结: 当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

创建分支修复BUG步骤:

  • 首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:

    $ git checkout master
    $ git checkout -b issue-101
    
  • 修复bug然后提交:

    $ git add file
    $ git commit -m "fix bug 101"
    
  • 修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:

    $ git checkout master
    $ git branch -d issue-101
    

Feature分支

每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。

如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。

$ git branch -D <name>

多人协作

查看远程库的信息:

$ git remote
origin

或者,用git remote -v显示更详细的信息:

$ git remote -v
origin  git@github.com:YangZhaobin/learngit.git (fetch)
origin  git@github.com:YangZhaobin/learngit.git (push)

如果没有推送权限,就看不到push的地址。

本地新建的分支如果不推送到远程,对其他人就是不可见的。

推送分支

推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上。

$ git push origin master
抓取分支

当从远程库clone时,默认情况下只能看到本地的master分支。

要在dev分支上开发,就必须创建远程origin的dev分支到本地:

$ git checkout -b dev origin/dev

当最新提交和你试图推送的提交有冲突,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:

git pull时,要指定本地dev分支与远程origin/dev分支的链接:

$ git branch --set-upstream dev origin/dev

从远程抓取分支,使用git pull,如果有冲突,要先处理冲突

标签管理

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。

其实它就是指向某个commit的指针

创建标签

  • 首先,切换到需要打标签的分支上:

    $ git checkout master
    
  • 然后,敲命令git tag <name>就可以打一个新标签:

    $ git tag v1.0  // 默认是给最新的一次commit设定标签
    
    $ git tag v0.9 6224937  // 给特定id的commit设定标签
    
  • 查看标签信息

    $ git show v0.9
    
  • 创建带有说明的标签

    $ git tag -a v0.1 -m "version 0.1 released" 3628164
    

操作标签

删除标签:

$ git tag -d v0.1

推送某个标签到远程:

$ git push origin v1.0

或者,一次性推送全部尚未推送到远程的本地标签:

$ git push origin --tags

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:

$ git tag -d v0.1

然后,从远程删除:

$ git push origin :refs/tags/v0.9
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值