Git 本质上是一种版本控制的工具
属于分布式版本控制系统(Distributed Version Control System,简称 DVCS):
在该类系统中,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
常见的有Git、Mercurial、Bazaar 以及 Darcs 等。其架构如下图所示:
版本控制的一般策略示例如下:
Mainline:主线,代码分支的树干,所有代码将合并到此分支。
Development:用户开发分支,每个人都可以基于主线分支创建自己的分支,在开发分支验证代码后,将提交请求,合并到主线分支。我们通常在本地的编译服务器中创建开发分支。
Feature:功能开发分支,只是针对一些可能影响主线的特殊功能,它不是稳定的。
Tag:标签不是分支,只是一个在一定的更改后的版本标记,标签版本不会在后续的开发中被更改,已释放发布的人工制品是来自于标签(或者说是按照标签进行相应的版本释放发布)。标签是回到历史版本的好方法。
Git 的安装
Linux Git: sudo apt-get install git
Windows Git: Git - Downloading Package
Git 账户创建(使用前完成):
$ git config --global user.name "Jack Ma"
$ git config --global user.email jack.ma@example.com
$ git config --global core.editor ’vim’
更改配置文件,便于后续查看清晰日志等:
$ cat .gitconfig
$ sudo vim .gitconfig
查看并添加以下信息:
[alias]
alog = log --decorate --graph --oneline --all
clog = log --decorate --graph --oneline
在创建好的文件夹中查询并获取、初始化git仓库:
$ mkdir test
$ git status
$ git init
$ ls -a
//查到有.git
$ git status //运行执行后,出现如下内容即为成功
Git 的三种状态
已修改(modified)、已暂存(staged)和 已提交(committed)
modified:表示修改了文件,但还没保存到数据库中。
staged:表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
committed:表示数据已经安全地保存在本地数据库中。
文件的修改、标记和上传涉及的流程及区域框图如下所示:
Working Directory:工作区,是对项目的某个版本独立提取出来的内容存放的区域。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
Staging Area:暂存区,是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。
Repository:Git 仓库目录,是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。
基本的 Git 工作流程如下:
-
在工作区中修改文件。
-
将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
-
提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。
如果 Git 目录中保存着特定版本的文件,就属于 已提交 状态。
如果文件已修改并放入暂存区,就属于 已暂存 状态。
如果自上次检出后,作了修改但还没有放到暂存区域,就是 已修改 状态。
工作目录中的每个文件都可以处于两种状态之一:跟踪或未跟踪。跟踪的文件是上次快照中的文件,以及任何新阶段的文件;它们可以未修改、已修改或已暂存。简而言之,跟踪的文件是 Git 知道的文件。具体如下图所示:
分支开发的基本工作流程:
-
基于远程分支,创建自己的临时分支;
-
切换到自己的临时分支上;
-
修改/添加暂存/上传到临时分支上;
-
获取以更新远程分支(即获取当前最新的远程分支);
-
将临时分支换基到远程分支上;
-
提交上传,等待评审;
-
合并后,删除当前临时分支。
Commit(上传)的示例:
对于不希望 Git 自动添加甚至显示未跟踪的文件。可以创建一个文件列表模式来匹配它们命名为.gitignore。
$ cat .gitignore //查看有哪些文件不是自动跟踪的
$ sudo vim .gitignore //进入添加一些不想自动跟踪的文件
一般文件过程及对应阶段的指令参照:
(1)touch b.c //创建新文件
(2)git status //此时,改文件处于已修改、但未暂存且未上传状态
(1)git add b.c //添加暂存文件b.c
(2)git status //此时,该文件处于已暂存但未上传状态
(1)git commit -m "the first change add to b.c" //添加暂存文件b.c
(2)git status //此时,该文件处于已上传,当前分支无需要上传的文件
(3)git log // 可以查看commit ID号以及修改的内容信息
修改后上传:
查询修改前后不同之处:
$ git diff
修改后重新暂存,然后上传:
删除已上传的文件:
b.c文件被完全删除,在未跟踪的状态中也不存在了:
上传日志查询:
$ git log
同样地,可以将日志与修改差异同时打印出来:
$ git log -p //图示略
$ git log --stat //图示略
创建分支的指令操作:
$ git branch testing // it will create a branch “testing”
$ git checkout testing // switch the working branch to “testing”
$ git checkout -b testing // Merge the above two command to one command
$ git branch -a // list all the remote and local branch
Git 怎么知道你目前在哪个分支上?它保留一个特殊的指头称为头(HEAD)。在 Git 中,这是指向当前的本地分支的指点。在这种情况下,您仍然处于主位。git 分支命令只创建了一个新的分支 - 它没有切换到该分支。
分支合并
Git 创建了一个新的快照,该快照来自此三向合并,并自动创建指向它的新提交。这称为合并提交,并且具有特殊性,因为它有多个父级。
指令:
$ git merge <branch name> // it will merge HEAD pointer branch with the destination branch
分支变基
变基之前:
变基之后:
通过变基指令操作,可以将一个分支上的改变移动到其他不同分支上。
指令:
$ git rebase <branch name or commit ID>
Cherry-pick
直接引用已经提交的某些更改。
如果存在一个或多个已提交,引用每个提交引入的更改,为每个提交记录新的提交(在你需要的分支上再提交一次)。这要求您的工作树是干净的(没有从头开始提交的修改)。
指令:
Git-fetch
从另一个repo存储库下载一些目标文件和参考资料
从一个或多个其他存储库获取分支和/或标签(统称为"参考"),以及完成其历史所需的对象。远程跟踪分支会被更新。
指令:
示例:
$ git fetch origin
Git-push
更新与目标物关联的所有远程参考
Gerrit push 指令:
$ git push origin HEAD:refs/for/<branch name>
示例:
$ git push ssh://username@master.gerrit.legato:29418/external/qct/sa515m HEAD:refs/for/le-2.1-afp //change to your path
Git-reset 定义
将当前头(HEAD)置向指定状态。
(1)$ git reset --soft
改变不涉及索引文件和工作树,仅将头指向<commit>, 这会使你的所有修改的文件变为待上传的状态,就像git指令的过程状态一样。
(2)$ git reset --mixed
重置索引,但不重置工作树(即,已更改的文件保留但未标记为暂存待提交),并报告未更新的内容。这是默认操作。
(3)$ git reset --hard
重置索引和工作树。自<commit>以来,对工作树中跟踪文件的任何更改都被丢弃。