Git && GitHub
我们应该明确一点Git是一个分布式的版本控制系统,和SVN这种集中式的版本控制相比,它有很多好处。
首先我们介绍下什么是集中式,什么是分布式版本控制系统。
在集中式版本控制系统中版本库是集中存放在一台单独的中央服务器的,在我们开始工作的时候需要先从中央服务器取得最新的版本,然后开始干活,最后再把自己的代码推送到中央服务器。
而分布式版本控制系统没有中央服务器的概念,每个人的电脑上有一个完整的版本库,因此在工作的时候,就不需要联网了。多人协作的时候就可以把各自的修改直接推送给对方,但是在实际使用分布式版本控制系统的时候,很少使用刚刚提到的那种直接推送的方式,一般分布式版本控制系统通常也有一台中央服务器,但这个服务器的作用仅仅是用来方便交换各自的修改的,没有中央服务器也一样可以工作,只是使用起来会比较不方便而已。
下面分别是SVN 和 CVN工作方式的视图(图片来自图解Git相关工作流)
上图中很明显得看出,SVN模式下要是中央服务器挂掉的话后果是十分严重的,而分布式版本控制系统,中有个Local Repository 如果中央服务器挂掉,可以使用这个代码库对其进行恢复。
下面就以一个简单的工作流展开介绍:
安装Git
配置Git
Git配置变量可能保存在如下三个地方:
/etc/gitconfig 文件:系统中对所有用户都适用的配置(若使用git config –system 时配置的是这个文件)
~/.gitconfig文件:只适用于当前用户的配置(若使用git config –global 时配置的就是这个文件)
.git/config文件:仅仅针对当前项目有效的配置。 (若使用git config 时配置的就是这个文件)
配置指令:
git config --global user.name “xiaohai.lin” |
查询配置:
git config --list |
代码仓库的创建
首先你要有个repo,repo的创建可以有两种方式一种是从无到有,一种是通过Clone 一份现有的代码作为开发的起点。
从无到有开始创建
mkdir myrepo 创建一个本地的目录
cd myrepo 进入到本地repo
git init 初始化repo这时候当前的目录转换成一个Git仓库。它在当前的目录下增加了一个.git文件夹,所有的提交将会都记录到这个文件夹下。
Clone 一份现有的代码作为开发的起点
git clone /path/to/repository (本地仓库的克隆)
git clone username@host:/path/to/repository (通过SSH)
git clone https:/path/to/repository.git (通过https)Fork Github上的某个项目作为开发起点
fork操作就相当于复制一份目标库(包括文件,提交历史,issues,和其余一些东西),通过fork你就可以自由得对项目进行修改而不用担心你的修改会影响到原始的项目。fork后仓库在你自己的GitHub帐号下。
下面就以fork butterknife这个项目为例来介绍如何fork:
首先进入这个项目的主页https://github.com/JakeWharton/butterknife。
点击项目主页右上角的fork图标。
这时候这个项目就会copy一份到你的github上。
但是有时候你还需要经常保持与原库保持同步,所以你需要使用如下的方式来同步项目。
git clone https://github.com/tbfungeek/butterknife.git
进入clone到本地的代码根目录,
git remote add upstream https://github.com/JakeWharton/butterknife.git
这时候就可以通过如下命令查看结果:
git remote -v
同步
从upstream 仓库 获取对应的分支和对应的提交,这些下载下来的提交存放在本地upstream/master 分支上。git fetch upstream
将本地代码切换到主分支
git checkout master
接下来就需要将你下载下来的upstream/master分支merge到本地的master
git merge upstream/master
但是这仅仅是同步本地的代码库,要同步到你Github上还需要push到Github上。
Clone the Remote
需要注意的是fork后代码只在你的Github上,如果需要下载到本地进行修改需要使用git clone
例子如下:
git clone https://github.com/tbfungeek/butterknife.git
这时候本地仓库由 git 维护的三棵“树”组成。第一个是你的工作目录,它持有实际文件;第二个是 缓存区(Index),它像个缓存区域,临时保存你的改动;最后是 HEAD,指向你最近一次提交后的结果。
创建一个本地的分支
当clone完一份代码后,推荐创建一个本地分支进行开发,这样可以避免对master等其他分支产生干扰。
分支是用来将特性开发绝缘开来的。在你创建仓库的时候,master 是“默认的”。在其他分支上进行开发,完成后再将它们合并到主分支上。
在git中提交时,会保存一个Commit对象,它包含一个指向暂存内容快照的指针,作者和相关附属信息,指向该提供对象直接祖先的指针。
Git中的分支,本质上仅仅是指向commit对象的可变指针,Git会使用master作为分支的默认名字。
HEAD 指向当前分支
git branch branchname 创建分支 |
切换到最新分支
git checkout branchname 切换到某个分支,这样HEAD就指向了指定的分支了。 |
本地操作
在介绍Git add/commit 之前需要先介绍下Git到底有哪些目录,各个阶段的文件分别存放在哪个地方:
三个工作区域:
- 工作目录
- 暂存区域(是一个简单文件,一般都放在git目录中,这个文件又可以称为索引文件)
- git 本地代码库
三种状态:
- 已修改(Modified):某个文件已经被修改但是还没提交保存
(自上次取出后,做了修改但是还没放到暂存区) - *已暂存(staged)*:把已修改的文件放在下一次提交时要保存的清单中了。
(在工作目录做了修改,并存放到暂存区) - *已提交(Committed)*:该文件已经被安全地保存在本地数据库中了
(git 代码库中保存的特定版本)
在提交之前需要先查看所要提交的文件处于那种状态,所以一般我们提交的时候会先用git status 查看下状态:
nothing to commit(working directory clean)
没有任何跟踪着的文件,没有任何文件在上次提交后更改过,当前没有出现处于未跟踪的新文件。(没有添加,也没有改动)
Untracked files:
(代码库中添加了新的文件,还没执行add)
Change to be committed
(说明当前已经处于暂存状态,如果此时提交,那么该文件此时此刻的版本将被留存在历史记录中,)
Change but not update
(已跟踪文件的内容发生变化,但是还没放到暂存区,要暂存这次更新需要运行git add 命令)
git add 把它们添加到暂存区,使用如下命令:
git add <filename> |
git commit -m "代码提交信息" |
Git commit只是将 暂存区域的内容提交到代码库。这里需要确认还有什么修改过的或者新建的文件没有git add过。否则提交的时候不会记录这些还没暂存起来的变化。
从下面图中可以很明显得看出各个操作的具体内容:
在提交的时候一般都会作两个工作就是运行git status 查看各个文件的状态,避免错误提交,
还有就是对比某个文件的内容的修改这个是使用git diff命令:
git diff: 查看 working directory 与 staging area 之间的差异 |
删除文件:
- 如果是Untracked 类型的文件可以直接使用rm
- 如果是已经add了需要 git rm -f 但是运行这个命令后,文件直接被删除,
如果你只是想退回到Untracked,则只需要git rm –cached test.md - Commit 后可以使用git rm 了 但是运行这个命令后,文件直接被删除.
回退修改:
这部分比较复杂可以根据下图的情况选择你所需要的:
这里只是介绍下如下几个简单的场景:
当你的修改还没add的时候想反悔怎么办:
git checkout -- <filename> |
此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到缓存区的改动,以及新文件,都不受影响。
git reset --hard <Commit ID> |
替换引用的指向。引用指向新的提交ID。
替换暂存区。替换后,暂存区的内容和引用指向的目录树一致。
替换工作区。替换后,工作区的内容变得和暂存区一致,也和HEAD所指向的目录树内容相同。
这个命令就会导致所有信息的回退包括文件内容,执行后文件内容无法恢复回来。
git reset <Commit ID>
即更改引用的指向及重置暂存区,但是不改变工作区。再次提交需要从git add做起
git reset --soft <Commit ID>
即只更改引用的指向,不改变暂存区和工作区。再次提交从git commit做起即可
假如你想要丢弃你所有的本地改动与提交,可以到服务器上获取最新的版本并将你本地主分支指向到它:
git fetch origin |
修补提交命令:
git commit --amend,用于对最新的提交进行重新提交以修补错误的提交说明或者错误的提交文件。 |
忽略某些文件:
有时候我们会有一些文件不需纳入Git管理,也不希望它们总是出现在未跟踪文件列表,我们可以创建一个名字为.gitignore的文件,列出需要忽略的文件模式。
.gitignore格式规范
所有以注释符号#开头的行都会被git忽略
可以使用标准的glob模式匹配
*表示匹配0个或者多个任意字符,
?匹配一个任意字符,
[],[-]
匹配模式最后跟/说明要忽略的是目录
要忽略指定模式以外的文件或者目录可以在模式前加上!取反
查看提交历史 :
git log |
将代码提交到远程代码库
添远程仓库(这种只会出现在第一次创建本地代码库并从零开始开发完提交到远程代码库的情况):
如果你还没有克隆现有仓库,并欲将你的仓库连接到某个远程服务器,你可以使用如下命令添加:git remote add origin <server>
git remote add repoShortName git://github.com/paulboone/ticgit.gitrepoShortName:简短仓库名可以用这个名字代替仓库地址了。一般远程服务名为origin
如此你就能够将你的改动推送到所添加的服务器上去了。推送数据到远程仓库
Git push origin master (这里不一定是master 可以是你本地的任何分支)
[remote name] [branch name]
获取最新代码
Git中可以通过 git fetch 以及 git pull 获取最新的代码,但是二者之间是有所区别的:
git fetch:相当于是从远程获取最新版本到本地,不会自动merge
git fetch origin master:tmp 将代码同步到本地的tmp分支,这时候使用使用git branch 可以看到这里有多出一个分支 |
这是个人比较推崇的一种方式。
git pull:相当于是从远程获取最新版本并merge到本地,相当于git fetch 和 git merge
在实际使用中,git fetch更安全一些,因为在merge前,我们可以查看更新情况,然后再决定是否合并
merge代码
当出现冲突的时候可以使用如下方式解决冲突:
git merge |
这时候就会要你选择使用那种merge工具
输入meld就可以使用meld来解决冲突了。
merge 完成后记得要需要执行如下命令以将它们标记为合并成功:
git add
git commit
一般merge完成后就可以删除这个没用的临时分支了:
git branch –d newbranch 删除分支 |
标签
在软件发布时创建标签,是被推荐的。可以执行如下命令以创建一个叫做 1.0.0 的标签:
git tag 1.0.0 1b2e1d63ff |
1b2e1d63ff 是你想要标记的提交 ID 的前 10 位字符。使用如下命令获取提交 ID:
分支操作命令总结:
创建分支 : git branch branchname |
远程代码库操作命令总结:
git remote –v查看当前配置有哪些远程仓库。 |
团队工作方式
Git 分支工作流
参考资料: