git初基本用法总结

RenaldoDeLo 9年前

来自: http://my.oschina.net/u/2491705/blog/618123


git是一个分布式版本控制系统

所谓的分布式管理控制系统就是不存在中央服务器,每一个电脑都有一个完整的版本库,不需要联网就可以工作。

分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是作为方便大家的修改。没有他,大家一样可以干活,只不过方便了交换而已


下面说下git的版本库,也可以说是git的仓库,英文repository,其实就是一个可以被git管理起来的目录而已。每一个文件的修改,删除git都可以追踪,以便git可以还原每一个历史的文件

创建一个版本库非常的简单,选择一个合适的地方


mkdir yangleiPro

cd yangleiPro

pwd


pwd命令是显示当前的目录,通过git init命令,把这个目录变成git可以管理的目录。

如上,git仓库就搞定,可以看到目录下面多了一个.git的东东。


有了repository,当然需要往我们的repository里添加项目文件,可以新建,也可以复制到yangleiPro目录下

用git add命令添加。

如果没有任何显示,就代表你添加成功了

添加完了文件,就可以提交文件了,把文件提交到仓库中。

用git commit命令。


通常我们可以


git commit -m "study git"


-m后面是对本次提交的说明性文件。


学习了创建版本库,add和commit文件。下面来说下git的操作


status命令和diff命令

git status命令可以让我们时刻的知道git的状态,比如一个文件被修改过,或者一个文件没有提交之类的

git diff命令顾名思义就是查看difference,也就是说git diff可以查看我们所修改的内容


版本回退

当我们提交了很多次文件后,想看看历史版本都有哪些,我们可以运行git log命令

git log命令用于现实从近到远的提交日志。

如果嫌输出的信息太多,可以用git log --pretty=oneline,此时你看到的一大串类似3628164...882e1e0的是commit id(版本号)。

每次我们提交一个版本,git就自动把他们串成一个时间线

回到某一个版本

首先git知道当前是哪一个版本,在git中用HEAD表示当前版本,上一个版本就是HEAD^,上上个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

git reset --hard HEAD^


如果想再重新恢复之前的版本,可以指定commit的id git log --pretty=oneline可以看到,

git reset --hard 3628164

ID那么长,不需要写全的,git会自动去找。

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL


注意,我们从这两节中可以了解到:


HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。

穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。

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


下面说下git的基本概念

工作区:这个简单,其实就是你电脑上的那个目录

版本库:工作区终有一个.git的文件,这个不属于工作去的,而是git的版本库

暂存区:stage或index,一半存在.git目录下的index文件中,所以我们把暂存区也叫做索引index


git的版本库中有很多东西,其中最重要的称为stage,也叫index,暂存区,还有git为我们自动创建的第一个分支,master,以及指向第一个分支的指针HEAD。

我们往git版本库中添加文件的时候通常分为两步

第一步:git add ,实际上是把文件添加到暂存区

第二步:git commit 实际上是把stage中所有的文件提交到当前的分支上。

因为我们创建版本库的时候,git会帮我们创建一个唯一的分支,所以现在我们提交到的分支就是git帮我们创建的master分支上。


当然,我们可以这么理解:需要提交的文件通通的放在stage暂存区中,然后一并提交到分支上。而且一提交后暂存区就没有任何内容了,而commit的内容也是从工作去中add到的stage中的内容


撤销修改

git checkout -- file可以丢弃工作区的修改

git checkout -- readme.txt的意思就是把其在工作去的修改全部撤销掉

这里有两种情况:


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

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

总之,就是让这个文件回到最近一次git commit或git add时的状态


删除文件

在git中删除其实也是一种对文件的修改

一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了

rm readme.txt

这个时候git知道你把文件给删了,因为工作区和版本库不一致了,用git status会告诉你哪些文件被删除了

所以现在你有两条路可以选择:

1、确定删除这些东西:git rm readme.txt

2、刚刚删除错了,需要恢复之前的工作区内容,git checkout -- readme.txt

命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。


下面说下git的远程仓库,其实所谓的远程仓库就是借用Github提供的git仓库托管服务

关于在Github上建立远程仓库这里就不多说了,百度也都是有很多的,而且一般我们的项目也是建立好的

简单介绍下把本地仓库的东东推送到远程仓库的做法吧

本地库的所有内容推送到远程库上

git push -u origin master

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

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

然后用命令git push origin master就可以了

注意:要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;关联后,使用命令git push -u origin master第一次推送master分支的所有内容;此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改


当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:


The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.

RSA key fingerprint is xx.xx.xx.xx.xx.

Are you sure you want to continue connecting (yes/no)?

  这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。


  Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:


Warning: Permanently added 'github.com' (RSA) to the list of known hosts.

  这个警告只会出现一次,后面的操作就不会有任何警告了。


下面说下git的clone,这是我们现在做项目的第一步,都是从clone下来项目经理已经建立好的项目框架

但是如果你是建立远程库的人,从远程库克隆,就需要我们先创建远程库,在github创建一个新的gitskills仓库,我们勾选Initialize this repository with a README,这样GitHub会自动为我们创建一个README.md文件。创建完毕后,可以看到README.md文件


真正的clone很简单,一个命令

git clone http://cloneurl


注意:要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快


下面说下分支的管理,这个可能是我们用的最多的地方了


看到这里,我们已经知道,我们的每一次提交,git都会把它串成一条时间线,这条时间线就是一条分支。目前来说,我们只说道一个分支,master。

HEADE严格来说不是指向提交,而是指向master,master才是指向提交的,所以HEAD指向的应该是当前的分支。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长,当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上,接着上面的说法,现在对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变。假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并,所以Git合并分支也很快!就改改指针,工作区内容也不变!和新建分支是一样一样的。


合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支


上面说的是指令和git分支管理的原理,下面说下具体的实现和指令:


首先我们创建一个分支,然后切换到这个分支上:

git branch yangleiDev

git checkout yangleiDev

当然这两句指令也可以直接写成一句:git checkout -b yangleiDev


然后我们可以用git branch来查看目前所有的分支,并且可以看到你现在所在的分支上。


然后我们可以在自己的分支上add,commit。。。各种操作

然后我们切回master分支,查看下内容,我擦!你会发现刚刚的提交什么的都不在了。。。

莫慌!因为你刚刚提交的是在自己的分支上,yangleiDev,而你现在在的是master分支上,所以这个时候我们需要做的就是把master指针移到自己新建的分支上,简单的说,就是分支的合并:git merge yangleiDev

git merge命令用于合并指定分支到当前分支


合并完成后就可以看到master分支上有了之前我们提交在yangleiDev分支上的东西了,这个时候就可以删了yangleiDev分支了:git branch -d yangleiDev

因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

命令比较多昂,这里简单总结下:


查看分支:git branch


创建分支:git branch <name>


切换分支:git checkout <name>


创建+切换分支:git checkout -b <name>


合并某分支到当前分支:git merge <name>


删除分支:git branch -d <name>


其实这么来说,一般操作就搞定了。。。但是!!!一般来说,由于是多人合作,所以这里我们一般都会遇到代码冲突

所谓的代码冲突就是不同的分支上有了新的提交,导致git无法执行快速合并


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

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


用git log --graph命令可以看到分支合并图。z


如果你有一个bug任务,你想创建一个分支issue-101来修复它,但是你当前正在dev上进行的工作还没有完成而不能提交,bug需要现在修复,所以现在你需要暂停dev上工作,Git提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:$ git stash。


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


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

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


对了,这里的分支有时候有个地方还是需要注意下的:

开发一个新feature,最好新建一个分支;如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除


下面介绍下关于分支的推送

当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且远程仓库的默认名称是origin


这里说道的远程库,如果需要查看远程库的信息,可以用git remote 活着用 git remote -v 查看更详细的信息。


推送分支

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

git push origin yourBranchName


master分支是主分支,因此要时刻与远程同步;

dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;

bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;

feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。


在我们现在的开发中,由于都是多人合作,所以一半的工作模式应该是这样子的:


首先,可以试图用git push origin branch-name推送自己的修改;

如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

如果合并有冲突,则解决冲突,并在本地提交;

没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!


如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name


其实说到这里就基本满足我们的工作需要了。

虽然git只是一个工具,但是却实实在在的写了一本书,关于git的一些高级的应用,其实我也不是很清楚,后续在研究补充,类似于git的标签,自定义git等等等操作。


好吧!先记录到这里吧~