Git的基本用法

1. Git的安装和配置
Git是目前世界上最先进的分布式版本控制系统。
CVS和SVN都是集中式的版本控制系统,而Git是分布式版本控制系统。
Git可以在很多平台上安装和运行,这里只介绍windows系统的安装方法。
可以到Git官网下载windows版本的软件,下载地址: https://git-scm.com/downloads
我下载的是最新版本 Git-2.10.1-64-bit.exe,下载完成之后直接双击,默认安装即可。
安装完成后,点击开始菜单中的 所有应用 → Git → Git Bash,弹出一个类似命令行的窗口,则说明安装成功。
然后,进行基本的配置,在刚刚的命令行窗口,输入如下命令:
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
因为Git是分布式版本控制系统,所以,每台机器都必须自报家门(你的名字和Email地址)。
注意:git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个全局配置,该全局配置文件是用户主目录下的一个隐藏文件.gitconfig(如:C:\Users\HP\.gitconfig)。
当然也可以对某个仓库指定不同的用户名和Email地址。局部配置文件,即针对某个仓库的配置文件为仓库目录下的 .git 目录中的 config 文件。

2. 创建版本库
版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
所有的介绍都以windows系统为例,linux系统类似,具体方法可自行百度。
首先,在D盘新建一个空目录Git。
然后,进入D:\Git目录,右键选择 Git Bash Here,打开Git Bash命令行窗口,就会以D:\Git为工作目录,输入下面的命令:
git init
初始化一个本地的Git版本库。
这样,Git就把版本库建好了,默认是一个空的仓库。可以发现版本库中有一个 .git 目录,该目录默认是隐藏的,这个目录是Git来追踪管理版本库用的。可以更改文件夹选项来显示隐藏的文件和文件夹。 也可使用 ls -ah 命令进行查看。

3. 把文件添加到版本库
使用Sublime编辑器或Zend Studio新建一个文件,推荐使用UTF-8编码,千万不要使用windows自带的文本编辑器,因为它会在每个文件的开头添加一个0xefbbbf(十六进制)的字符来保存UTF-8编码的文件。这可能导致很多出乎意外的问题。
现在,我们在版本库目录D:\Git下,新建一个 readme.txt文件,内容如下:
Git is a version control system.
把文件添加到Git版本库,需要两个步骤:
第一步,用命令 git add 告知Git,需要把哪些文件添加到版本库。这一步,其实是将文件添加至暂存区或缓存区。
git add readme.txt
也可以使用git add . 或 git add *,一次性将当前目录中的所有内容添加至缓存区。
第二步,用命令 git commit 告诉Git,把缓存区中的待提交文件提交至版本库。
git commit -m "add a readme.txt"
注意:git commit 命令,-m 后面的字符串表示注释说明的内容,必须书写。

4. 查看版本库的状态
git status
如果我们将readme.txt文件进行修改,改为下面的内容:
Git is a version control system.
Git is free software.
保存之后,再来执行命令 git status,就会发现提示信息说,文件readme.txt已经被修改了,但是还未提交。

5. 查看更改的具体内容
git diff
如果想查看readme.txt具体修改了什么内容,可以使用命令 git diff readme.txt,知道具体更改了哪些内容后,我们就可以放心地提交了。接下来,执行下面的提交命令即可:
git add readme.txt
git commit -m "edit a readme.txt"

6. 查看版本库被修改的历史记录
git log
如果嫌输出信息太多,看得眼花缭乱的,可以加上--pretty=oneline参数,即使用下面的命令:
git log --pretty=oneline
git log命令会显示从最近到最远的提交日志,每一行的前面的一大串字符(如8049b6d388b6dbe165050853711efdff6769aec3)是commit id(版本号),它和SVN的版本号不一样,Git的版本号不是递增的数字,而是一个SHA1加密计算出来的一个非常大的数字,用十六进制表示。

7. 回退到历史版本
有时,我们需要将Git版本库回退或还原到以前的某个版本,可以使用 git reset 命令。
首先,Git必须知道当前是哪个版本,在Git中,HEAD表示当前版本,也就是最新的commit id,上一个版本是 HEAD^,上上一个版本就是 HEAD^^,上50个版本可以写成 HEAD~50。
现在,我们使用下面的命令,将Git回退到上一个版本:
git reset --hard HEAD^
这时,我们再来使用 git log 命令查看版本库被修改的日志。却发现,看不到被回退的版本之后的历史记录了。如果,想再回到最新的版本,怎么办?
只要刚刚的Git Bash命令行窗口没有关掉,你就可以顺着往上面找,直到发现最新的版本号(如4b2a0c88a2d03675694013ac6a2bd6f55c830cdc),于是,就可以使用下面的命令还原到指定的版本:
git reset --hard 4b2a0c8
版本号没必要写全,一般写前七位就够了,Git会自动去匹配。
这样,就又回到了最新的版本。Git的版本回退速度非常快,因为Git在内部有一个指向当前版本的HEAD指针,当回退版本的时候,Git仅仅是把HEAD的指针指向进行了更改。
如果,你回退到了某个版本后,把电脑关了。第二天又后悔了,想要恢复到最新版本,这时,可以使用命令 git reflog 来查看你的每一次操作日志,该命令可以输出对应的版本号的操作记录。这样,我们就可以恢复到任意版本了。

8. 工作区和暂存区
Git和其他的版本控制系统(如SVN)不同,Git有暂存区(或缓存区)的概念。
工作区(Working Directory):就是你在电脑里能看到的目录或你存放代码文件的目录。如D:\Git目录。
版本库(Repository):就是你执行git init初始化命令的目录,当你在一个工作区中执行git init时,当前的工作区目录就变成了版本库目录。版本库中有一个隐藏目录 .git,它是用来追踪管理版本库的。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
分支和HEAD的概念我们后面再讲。
前面我们说到,把文件添加到版本库,是分两步执行的:
第一步,是用 git add 把修改或新增的文件添加到暂存区;
第二步,是用 git commit 提交更改,即把暂存区里的所有内容提交到当前的分支。
因为,我们创建Git版本库时,Git自动为我们创建了一个唯一的master分支,所以,执行 git commit 命令就是向master分支提交更改。
可以简单理解为,需要提交的文件修改通通先放到暂存区,然后一次性将暂存区中的所有修改提交到版本库的当前分支。

9. 管理修改和撤销修改
Git之所以比其他版本控制系统设计得优秀,是因为Git跟踪并管理的实际上是修改,而非文件。
什么是修改?比如,你新增了一个文件,这就是一个修改,或者你新增了一行或更改了某些字符,这都算一个修改。
假如,有一个文件,你对其进行了第一次修改,并使用 git add 添加到暂存区;然后,你又对其进行了第二次修改,却没有添加到暂存区,此时,你执行 git commit 命令提交了修改。结果发现,只有第一次的修改被提交了。因为,git commit 命令只会把暂存区中的修改而非文件提交给版本库的当前分支。
这样我们就知道,每次修改,如果不 git add 到暂存区中,就不会被 git commit 提交。

如果你修改了某个文件(如readme.txt),但还没有提交到版本库。想要丢弃修改,这时可以使用下面 的命令:
git checkout -- readme.txt
来丢弃工作区的修改。
命令 git checkout -- readme.txt 的作用就是,把文件在工作区的修改全部撤销,这里有两种情况:
一种是readme.txt文件自修改后,还没有添加到暂存区,现在,撤销修改就会回到和版本库一模一样的状态;
一种是readme.txt文件添加到暂存区后,又作了修改,现在,撤销修改就会回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次 git commit 或 git add 时的状态。
注意:git checkout 后面的 -- 很重要,如果没有 -- ,就变成了“切换到另一个分支”的命令。这在后面的分支管理中进行介绍。

如果你修改了文件readme.txt,并且添加到了暂存区,这时你想把暂存区中的修改撤销,重新放回工作区,可以使用下面的命令:
git reset HEAD readme.txt
git reset 命令既可以回退版本,也可以把暂存区中的修改撤销。

场景一:当你改乱了工作区某个文件的内容,想直接丢弃工作区中的修改时,用命令git checkout -- filename。
场景二:当你不仅改乱了工作区中某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD filename撤销暂存区的修改,就回到了场景一;第二步按场景一操作。
场景三:当你不仅改乱了工作区中某个文件的内容,而且还提交到了本地版本库,想要撤销本次的提交时,可以使用回退到历史版本的命令。不过,前提是还没有推送到远程的版本库。
提示:多用 git status 命令,不仅可以查看版本库的当前状态,还可以看到相关操作的提示信息。

10. 删除文件
在Git中,删除也是一个修改操作。
假如,现在我们新创建了一个文件test.php,并且已经提交到了本地版本库。这时,你直接在电脑硬盘目录中删除了该文件。Git知道你删除了文件,工作区和版本库就不一致了。可使用 git status 命令查看版本库的状态。
现在,你有两个选择,一是确实要从版本库中删除该文件,那就用命令 git rm 删除,并且 git commit 提交。方法如下:
git rm test.php
git commit -m "remove test.php"
另外一种情况是,你在本地删错了,但版本库中还有,所以可以很轻松地把误删的文件恢复到工作区。方法如下:
git checkout -- test.php
提示:git checkout -- filename 其实是用版本库中的文件版本替换工作区的版本,无论工作区是修改还是删除,都可以还原。
当然,要删除一个版本库中已有的文件,可以省去从本地磁盘目录删除文件的步骤,直接使用命令 git rm test.php 和 git commit -m "remove test.php"。

11. 远程仓库
Git是分布式的版本控制系统,同一个Git仓库,可以分布到不同的机器上。肯定只有一台机器上有一个原始的版本库,此后,别的电脑可以克隆这个原始的版本库,而且,每台机器克隆的版本库都是一样的,没有主次之分。
情况是这样的,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个中央服务器的仓库克隆一份到自己的电脑上,并且各自都可以把各自的提交推送到中央服务器的仓库里,也可以从中央服务器仓库中拉取别人的版本。
我们完全可以自己搭建一台运行Git的中央服务器,不过,现阶段学Git先搭建个中央服务器有点小题大做。有个叫GitHub的网站,提供了Git仓库托管服务,只需注册一个GitHub账号,就可以免费获得Git远程仓库。
请先自行注册GitHub账号。由于本地Git仓库和GitHub远程仓库之间的传输是通过SSH加密的。故先要进行如下的配置:
第一步:创建SSH Key。
在用户主目录下(window环境是C:\Users\HP),看看有没有 .ssh 目录,如果有,再看看这个目录下有没有 id_rsa 和 id_rsa.pub 这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Window环境下打开Git Bash),创建 SSH Key:
ssh-keygen -t rsa -C "youremail@example.com"
把邮件地址换成你自己的邮件地址,然后一直回车,使用默认值即可。由于这个Key也不是用于军事目的,所以也无需设置密码。
顺利的话,就可以在用户主目录里找到 .ssh 目录,里面有 id_rsa 和 id_rsa.pub 两个文件,它们分别是SSH Key的私钥和公钥。id_rsa是私钥,不能泄露出去;id_rsa.pub是公钥,可以告诉其他人。

第二步:登录GitHub账号,点击账户头像下三角符号处的用户设置 Settings,进入 SSH and GPG keys 设置页面。
然后,点击“New SSH key”,新增一个SSH key,填上任意的Titile,在Key文本框内粘贴 id_rsa.pub 文件的内容。点击 “Add SSH Key”按钮确认。

为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
当然,GitHub允许添加多个Key。假设你有若干电脑,你有时在公司推送,有时在家里推送,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub远程仓库推送了。
友情提示:在GitHub上免费托管的Git仓库,任何人都可以看到(但只有你自己才能修改)。所以,不要把敏感信息放进去。
如果不想让别人看到你的Git仓库,有两个办法:一是给GitHub交点保护费,让GitHub把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写);另一个办法是自己动手搭建一个Git服务器。

12. 添加远程仓库
现在的情景是,你已经在本地创建了Git仓库(本地Git版本库),又想在GitHub上创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作。
首先,登录GitHub,点击 New repository 按钮,新创建一个远程仓库。输入仓库的名称和描述后,确认创建即可。
我创建的远程仓库的名称为 HP-Git,目前,在GitHub上的这个仓库还是空的,我们可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。
现在,我们根据GitHub的提示,在本地的Git仓库下(D:\Git),打开Git Bash,运行下面的命令:
git remote add origin https://github.com/yjj353373397/HP-Git.git
千万注意:把上面的yjj353373397替换成你自己的GitHub用户名,否则,你在本地关联的就是我的远程仓库,关联没有问题,但是你推送会出现问题,因为你本地的SSH Key公钥,并不在我的GitHub的SSH Key列表中。
执行上面的命令后,远程库的名字就是origin,这是Git的默认叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。
下一步,就可以把本地库的所有内容都推送到远程库上,即执行下面的命令:
git push -u origin master
把本地库的内容推送到远程库,用 git push 命令,实际上是把本地的当前分支master推送到远程库的分支master。执行上面的命令后,会要求你输入GitHub的账户和密码,输入正确的账户和密码登录即可开始推送。
由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支推送到远程新的master分支,而且会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时,就可以简化命令。
推送成功后,可以立刻在GitHub页面中看到远程库的内容已经和本地库的一模一样。
从现在起,如果本地作了提交,就可以通过命令:
git push origin master
把本地的master分支的最新修改推送到GitHub,现在,你就拥有了真正的分布式版本库。
小结:
要关联一个远程库,首先你得有一个远程库,然后使用命令 git remote add origin https://github.com/yjj353373397/HP-Git.git 进行关联;
关联之后,使用命令 git push -u origin master 第一次推送master分支的所有内容到远程库,会要求你输入GitHub的账户和密码;
此后,本地所作的修改,提交到本地版本库后,只要有必要,就可以使用命令 git push origin master 推送最新的修改到远程库,而不用输入GitHub的账户和密码。
分布式版本控制系统Git的最大好处之一是在本地工作时完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作;而SVN在没有联网的时候是拒绝干活的!

13. 从远程库克隆
上面,我们讲了先有本地库,后有远程库的时候,如何关联远程库,并将本地库的内容推送至远程库。
现在,假设我们从零出发,那么最好的方式是先创建远程库,然后,从远处库克到本地。
首先,登录GitHub,创建一个新的仓库,名称为 Remote-first,并勾选 Initialize this repository with a README 前面的复选框(默认是没有勾选的),这样,GitHub会自动为我们创建一个README.md文件,作为整个远程库的说明文档。创建完毕后,就可以看到README.md文件。
现在,远程库已经准备好了,下一步是用命令 git clone ,将远程库克隆到本地库。方法如下:
点击远程库右侧的 “Clone or download”按钮,复制远程库的URL地址(如 https://github.com/yjj353373397/Remote-first.git),进入本地电脑的D盘,右键选择 Git Bash Here,打开 Git Bash 的命令行窗口后,输入下面的命令:
克隆完毕后,在本地电脑的D盘,就会出现一个文件夹 Remote-first,里面的内容和远程库的一样。
如果多人协作开发,那么每个人各自从远程库克隆一份到本地就可以了。
也可以用 git clone git ://github.com/yjj353373397/Remote-first.git 来进行克隆。
要克隆一个远程仓库,首先必须知道仓库的地址,然后使用 git clone 命令克隆到本地。Git支持多种协议,包括https和git协议,git协议的速度更快,git协议使用ssh。

14. 分支管理
假设你准备开发一个新的功能,但需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码会导致别人不能干活。如果等代码全部写完再一次提交,又存在丢失每天进度的风险。
现在,有了分支,就好解决了。你可以创建一个属于自己的分支,别人看不到,还继续在原来的分支上工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不会影响别人工作。
其他版本控制系统如SVN,它也有分支管理,但是用过之后,你会发现,它创建和切换分支比蜗牛还慢,让人无法忍受,结果SVN的分支功能就成了摆设,大家都不去用。
但Git的分支是与众不同的,无论创建、切换还是删除分支,Git都很快能完成。

15. 创建与合并分支
每次git add 和 git commit(提交),git都把它们串成一条时间线,这条时间线就是一个分支,默认分支为master(主分支)。
截止目前,只有一条时间线,在git里,这个分支叫主分支,即master分支。
严格来说,HEAD是指向当前分支,而默认的当前分支为master,master才是指向提交的。
刚开始的时候,master分支是一条线,git用master指向最新的提交,再用HEAD指向master,就能确定当前分支和当前分支的提交点。
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。
当创建新的分支,如dev时,git会新建一个同名指针dev,指向master相同的提交点,再把HEAD指向dev,就表示当前分支为dev。
git创建分支很快,就增加了一个dev指针,同时更改HEAD的指向,工作区的文件没有任何变化。创建分支dev后,对工作区的修改和提交就是针对dev分支了。比如,新提交一次后,dev指针向前移动一步,而master指针不变。
假如,我们在dev分支上的工作完成了,就可以把dev分支合并到master主分支。git怎么实现分支合并呢?最简单的方法,就是直接把master分支指向dev的最新提交点,就完成了合并。因此,Git合并分支也很快,就是简单的更改一下指针,工作区的内容没有变化。
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针删掉,删掉后,就只剩下一条master主分支。
下面开始实战。
首先,创建dev分支,并切换到dev分支。
进入本地版本库目录D:\Git,右键选择 Git Bash Here,执行下面的命令:
git checkout -b dev
说明:git checkout 命令后加上 -b 参数,表示创建并切换分支。故上面的命令等同于下面的两条命令。
git branch dev
git checkout dev
然后,用git branch命令查看所有的分支名称和当前分支。
git branch
当前分支前面会标一个 * 星号。
然后,我们就可以在dev分支上进行提交操作了。先修改一下工作区的文件内容,如readme.txt,新增一行:
Creating a new branch is quick.
然后,提交到本地版本库的dev分支。
git add readme.txt
git commit -m "branch test"
现在,dev分支的工作已完成了,我们就可以切换回master主分支。
git checkout master
切换回master分支后,再查看一下工作区中readme.txt文件的内容,发现,刚才新增的一行内容不见了。这是因为dev分支上才有最新的提交,而master分支的提交点还没有变。
现在,我们把dev分支的最新工作成果合并到master分支上,命令如下:
git merge dev
说明:git merge 命令用于合并目标分支到当前的分支。
合并分支后,再来查看readme.txt文件的内容,发现它和dev分支的最新提交是完全一样的。
这种合并方式是Fast-forward,它直接把master分支指向了dev分支的最新提交点。所以,合并的速度非常快,但是,也不是每次合并都能使用Fast-forward模式,后面我们再讲其他的合并方式。
合并完成后,就可以删除dev分支了,命令如下:
git branch -d dev
可以发现,创建、合并和删除分支非常快,所以Git推荐使用分支完成某个任务,合并后再删除分支。这和直接在master分支上的工作效果是一样的,但过程更安全。

16. 解决冲突
冲突的产生:
比如,我们创建了一个新的分支test,在分支上对某个文件(readme.txt),进行了修改,并提交。然后,我们切换到主分支master,也对同样的文件进行了修改,并提交。再把test分支合并到主分支的时候,就会提示冲突。
首先,创建分支并切换到分支test。
git checkout -b test
然后,修改readme.txt文件的最后一行,改为:
Creating a new branch is quick and simple.
在test分支上进行提交。
git add readme.txt
git commit -m "and simple"
然后,切换到master分支。
git checkout master
在master分支上,也修改readme.txt文件的最后一行,改为:
Creating a new branch is quick and easy.
在master分支上提交。
git add readme.txt
git commit -m "and easy"
这种情况下,Git无法正确执行快速合并(Fast-forward模式),会产生冲突。
git merge test
提示信息如下:
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
这种冲突,必须手动解决后,再来提交。
冲突的解决:
手动修改一下发生冲突的文件,重新提交一次即可解决。
打开readme.txt文件,冲突的部分为:
<<<<<<< HEAD
Creating a new branch is quick and easy.
=======
Creating a new branch is quick and simple.
>>>>>>> test
我们将readme.txt中上述冲突部分,改为下面的内容:
Creating a new branch is quick and easy.
然后,再重新提交一次:
git add readme.txt
git commit -m "conflict fixed"
最后,我们删除test分支。
git branch -d test

17. 分支管理策略
通常,我们都是使用下面的命令,快速合并分支:
git merge dev
但这种模式下,删除分支后,在当前分支master上,就看不到分支dev的信息。
如果我们想保留分支的历史信息,可以禁用Fast-forward模式,这样,Git就会在merge时,生成一个新的commit。这样,从master分支历史上,就可以看到dev的分支信息了,也就是说清楚地知道曾经对哪个分支做过合并操作。
合并分支时,采用下面的命令进行合并,禁用Fast-forward模式:
git merge --no-ff -m "merge with no-ff" dev
合并后,使用git log命令,查看当前分支的历史信息:
git log --graph --pretty=oneline
分支策略:
在实际开发中,应该按照以下几个基本原则进行分支管理:
首先,主分支master应该是非常稳定的,仅用它来发布新版本,平时,不能在它上面进行开发。
创建一个分支dev,用来在它上面干活(开发)。也就是说,dev分支是不稳定的,需要发布项目版本(如1.0)时,再把dev分支合并到master主分支,在master分支上发布新版本。
所有的项目开发人员都在dev分支上干活,每个人也都有自己的分支,时不时往dev分支上合并就可以了。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值