git初基本用法总结
来自: 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等等等操作。
好吧!先记录到这里吧~