PS:本文整理修改自Git与Repo入门
1.什么是git与repo?
Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。git不是简单复制指定版本的快照,而是把所有的版本信息仓库全部同步到本地,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连网时push到相应的服务器或其他用户那里。由于每个用户那里保存的都是所有的版本数据,所以,只要有一个用户的设备没有问题就可以恢复所有的数据。当然,这增加了本地存储空间的占用。
而repo则是Google用python脚本写的调用Git的脚本,主要用来下载、管理android项目的软件仓库。
2.如何使用git?
1.获得GIT仓库
有两种获得GIT仓库的方法,一是在需要用GIT管理的项目的根目录执行:
git init
执行后可以看到,仅仅在项目目录多出了一个.git目录,关于版本等的所有信息都在这个目录里面。
另一种方式是克隆远程目录,由于是将远程服务器上的仓库完全镜像一份至本地,而不是取某一个特定版本,所以用clone而不是checkout:
git clone <url>
2.GIT文件操作
版本控制就是对文件的版本控制,对于Linux来说,设备,目录等全是文件,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。
GIT仓库所在的目录称为工作目录,这个很好理解,我们的工程就在这里,工作时也是在这里做修改。
在工作目录中的文件被分为两种状态,一种是已跟踪状态(tracked),另一种是未跟踪状态(untracked)。只有处于已跟踪状态的文件才被纳入GIT的版本控制。如下图:
那么,我们怎么知道当前工作目录的状态呢?哪些文件已被暂存?有哪些未跟踪的文件?哪些文件被修改了?所有这些只需要一个命令,git status,如下图所示:
了解了文件状态,我们就可以对项目中的文件进行增删改查、提交、撤销等操作了。
- 添加文件到缓冲区
git add <file>(包含路径)
- 从缓冲区撤销添加文件
git reset HEAD <file>
- 查看文件的具体改动:
gitk
git diff
如图所示:
通过git diff查看增加和删除的代码一目了然。
- 删除文件
git rm <file>
- 恢复代码为最近一次提交的状态
git stash
3.GIT提交仓库
- 增加仓库地址
git remote add 仓库名称 git路径
- 当前仓库地址查看
git remote -v
- 重置仓库地址
git remote set-url 仓库名称 git路径
- 提交到本地仓库(case为本次提交的说明字段)
git commit -m "case"
- 跳过git add 暂存直接提交到本地仓库
git commit -a
- 仓库代码更新
git pull 仓库 master
- 提交到remote仓库
git push 仓库名称 master
- 察看文件提交历史
git log --name-only 文件
- 撤销提交
前面说了删除提交的方法,但是如果是多人合作的话,如果某个提交已经Push到远程仓库,是不可以用那种方法删除提交的,这时就要撤销提交:
git revert <commit-id>
这条命令会把指定的提交的所有修改回滚,并同时生成一个新的提交。
- Reset
git reset [options] <commit>
这条命令会使HEAD提向指定的Commit,一般会用到3个参数,这3个参数会影响到工作区与暂存区中的修改:
--soft: 只改变HEAD的State,不更改工作区与暂存区的内容
--mixed(默认): 撤销暂存区的修改,暂存区的修改会转移到工作区
--hard: 撤销工作区与暂存区的修改
至此git的基本使用就说完了,这里可以做一个简单的提交代码的模拟:
- 1.拉代码
git clone
- 2.根据具体需求修改好代码后,先要更新一下代码(避免与仓库中的代码不同步)
git pull
然后将我们的差分包合入后
git status
- 3 根据终端中的提示将我们修改过的文件或目录逐一添加
git add
- 4提交本地库
git commit -m "case"
- 5 提交remote库
git push 仓库 master
然后初步修改提交就完成了。
4.GIT分支
分支被称之为GIT最强大的特性,因为它非常地轻量级,如果用Perforce等工具应该知道,创建分支就是克隆原目录的一个完整副本,对于大型工程来说,太费时费力了,而对于GIT来说,可以在瞬间生成一个新的分支,无论工程的规模有多大,因为GIT的分支其实就是一指针而已。在了解GIT分支之前,应该先了解GIT是如何存储数据的。
前面说过,GIT存储的不是文件各个版本的差异,而是文件的每一个版本存储一个快照对象,然后通过SHA-1索引,不只是文件,包换每个提交都是一个对象并通过SHA-1索引。无论是文本文件,二进制文件还是提交,都是GIT对象。
-
分支引用
所谓的GIT分支,其实就是一个指向某一个Commit对象的指针,像下面这样,有两个分支,master与testing:
而我们怎么知道当前在哪一个分支呢?其实就是很简单地使用了一个名叫HEAD的指针,如上图所示。HEAD指针的值可以为一个SHA-1值或是一个引用。
- 新建分支
git branch <branch-name>
- 切换分支
git checkout <branch-name>
- 删除分支
git branch -d <branch-name>
- 分支合并(merge)
当我们新建一个分支进行开发,并提交了几次更新后,感觉是时候将这个分支的内容合回主线了,这是就可以取出主线分支,然后把分支的更新merge回来:
git checkout master
git merge testing
如果master分支是testing分支的直接上游,即从master延着testing分支的提交历史往前走可以直接走到testing分支的最新提交,那么系统什么也不需要做,只需要改变master分支的指针即可,这被称之为"Fast Forward"。
但是,一般情况是这样的,你取出了最新的master分支,比如说master分支最新的提交是C2(假设共3次提交C0<-C1<-C2),在此基础上你新建了分支,当你在分支上提交了C3、C5后想将br1时merge回master时,你发现已经有其他人提交了C4,这时候就不能直接修改master的指针了,不然会丢失别人的提交,这个时候就需要将你新建分支时master所在的提交(C2)后的修改(C4),与你新建分支后在分支上的修改(C3、C5)做合并,将合并后的结果作为一个新的提交提交到master,GIT可以自动推导出应该基于哪个提交进行合并(C2),如果没有冲突,系统会自动提交新的提交,如果有冲突(这几次push修改了相同的文件),系统会提示你解决冲突,当冲突解决后,你就可以将修改加入暂存区并提交。提交历史类似下面这样:
5.GIT&&REPO配置
略
6. REPO
- 在当前目录下初始化repo
会在当前目录生生成一个.repo目录,像Git Project下的.git一样,-u指定url,可以加参数-m指定manifest文件,默认是default.xml,.repo/manifests保存manifest文件。.repo/projects下有所有的project的数据信息,repo是一系列git project的集合,每个git project下的.git目录中的refs等目录都是链接到.repo/manifests下的。
repo init -u <url> [OPTIONS]
- 同步Code
repo sync
- 查看所有分支
repo branch或repo branches
- 查看本地所有Project的修改,在每个修改的文件前有两个字符,第一个字符表示暂存区的状态,每二个字符表示工作区的状态
repo status
- 撤销整个工程的本地修改
repo forall -c 'git reset --hard HEAD;git clean -df;git rebase --abort'
- 查看修改
repo diff
- 切换整个工程模块的分支
repo forall -c 'git branch master'
- 更新整个工程模块的代码
repo forall -c 'git pull projectname'