本篇主要讲Git 的一些基础和一些在开发中比较常用的命令。比较适合初学和快速了解Git。
Git文件分类
Git中的文件分为三类:已追踪的(Tracked)、被忽略的(Ignored)、未追踪的(Untracked)。
已追踪的(Tracked):是对文件进行过git add xxx 操作的文件。
被忽略的(Ignored):在版本库中声明为不可见或者被忽略的文件??梢杂美粗付ê雎宰纷倌骋惶囟ㄎ募?,或忽略某一类文件。Git允许在版本库中任何目录下有.gitignore文件,每个文件都只影响该目录及所有其子目录。配置忽略文件:
$ cd my_package
$ cat .gitignore
*.o
这样Git会忽略所有版本库中所有的.o文件。但有时需要追踪被忽略中特定的文件,可以这样进行配置:
$ cd my_package/vendor_files
$ cat .gitignore
!driver.o
这样vendor_files子目录下的driver.o文件就会被追踪了。
未追踪的(Untracked):不是已追踪的和被忽略的就是未追踪的。可以将Git工作目录所有文件看成一个集合,去除已追踪的和被忽略的,那就剩下未追踪的了。
Git add
git add 将一个未追踪的文件转成已追踪状态,如果是git add作用文件夹,那文件夹下的所有文件都会被追踪。使用git add时可以先用git status 查看文件状态。
Git rm
与git add 命令相反,从工作目录和索引中删除一个文件,并不会删除该文件在版本中的历史记录。
Git commit
git commit 把文件从stage提交到branch;git commit -a 把修改的文件先提交到stage,然后再从stage提交到branch。使用git commit -a 包括提交自动暂存的文件和新增未追踪的文件 还有从工作副本中删除已追踪的文件。
Git log
提交完成后,可以使用git log 查看提交历史记录,每次提交都会有唯一的40位16进制SHAI提交ID(显示引用),无论提交处于版本库历史中的任何位置,哈希ID都对应相同的提交。
Git bisect
git bisect 命令是一个强大的错误查找工具,基于任意搜索条件查找特定的错误提交。当发现版本库中有问题,而之前是好的,就可以使用git bisect 命令了。其实就是当测试说程序这里发现bug了,WT? 但之前明明是好的啊。这种情况就可以用git bisect 来检查了。
git bisect 原理是通过二分法来查找产生问题的提交。使用之前你需要确定代码在哪次提交前是没问题的,和代码哪次提交已经出现问题了(一般就是当前的HEAD)。即确定一个good点 和一个bad点,然后重复回答这个版本是否能未出现问题,直到确定问题所在的提交为止。流程演示:
1、进入git工作区间
2、使用git log 查看所有历史提交
在上面这个版本库中现在假如在最后一次提交时出现问题了,但是我确定在 “create project” 之前是没问题的。
现在来确定出现问题的commit。
3、按顺序执行下面命令
// 开始使用bisect
git bisect start
// 设置目前的版本是坏的,已经出现问题
git bisect bad
// 设置“HEAD~5” 提交之前是好的
git bisect good HEAD~5
HEAD~5 是怎么获取到的呢?在输入git bisect good 时按tab键会有提示,里面HEAD~5对应的就是create project提交。HEAD~5其实表示的是提交范围(相当于游标)。
4、开始查找出错提交
输完上面命令后如下:
现在只要一直输入 git bisect good/bad 确定出现提交的“好” “坏”。我上面的是“修改ViewController.h” 这次提交,提交这次后是没有问题的,所以输入git bisect good
命令行会再出现某一次的提交供你判断?!靶薷腁PPDelegate.h” 这次提交也是没有问题的。继续输入git bisect good。
5、确定出先问题提交
出现上面的信息就可以知道使用git bisect 已经确定了出问题的提交了。“修改info.plist” 这次提交出现问题,修改人员和时间信息都有。
使用git bisect 其实是在一个新的分支上进行的,不用担心对当前版本有干扰,输入git branch 查看当前分支。
其实在命令行中 紫色git 后面的括号中就是当前分支(因为我是用了Oh My Zsh 命令行扩展工具)。
Git 分支
分支是软件项目中启动一条单独开发线程的基本方法。
分支主要的应用情景:
1、项目需要开始一个新版本,假如为1.1,但需要保留1.0的版本,开新分支作为一个新的1.1版本。
2、封装开发阶段。项目要发布时进行测试、维护,可以新开一个分支作为测试或维护版本。
3、在研究复杂的功能或者复杂的bug时,可以开一个分支,来完成一个孤立任务,完成后合并即可。
git init 初始化的时候默认会有一个主分支master ,在取分支名时需要注意一些规则。分支名不能以“/”斜线结尾,不能以“-”减号开头,分支名不能包含“..”两个连续的点,不能有空格,不能含有特殊含义的字符(包括 ~ ^ : ? * [ ) 。
分支使用:
查看分支(获取分支列表): git branch ? 也可以使用 git show-branch查看更详细的输出。
* 星号后面就是当前分支,因为当前版本库中就只有一个主分支master,所以就列出了一个maser。
创建分支: git branch branchName(创建的分支名) ,创建完成后可以使用git branch查看。
可以看到新的分支已经创建好了。如何检出(切换)分支呢? 可以使用git checkout branchName切换。检出完成使用git branch 查看当前分支。
在检出分支时可能会遇到有未提交更改的情况,当前分支下对文件做了更改,但未提交,Git不会删除和修改这些文件。但是如果一个文件的本地修改和新分支上的更改不同时(修改同一文件发生冲突),Git会发出错误信息,拒绝检出目标分支。
先使用git status 查看当前分支的文件更改。
可以看到我对UserInterfaceState.xcuserstate和ViewController.m做了修改,使用Oh My Zsh直接可以看出,当前分支newBranch后有叉就代表有修改未提交的文件,挺好用的。然后进行检出master,再使用git status 查看。
可以看出修改的文件已经到我们检出的master分支下了,然后再根据需求在提交的分支进行提交git commit -a。
合并分支: git merge branchName ?将branchName分支合并到当前分支。
多个分支时,合并分支有时会出现合并冲突,可以看下这篇《git 合并冲突处理》。
Git diff
可以比较两个项目状态的所有不同。git diff 命令进行比较时,可以通过提交名、分支名和标签(tag)进行比较。SVN和Git在产生diff中就存在差异,diff和patch在Git中是导出的数据,SNV和CVS中是基本数据,进入.git .svn就可以看出.git中是没有diff文件的,但是.svn会有大量的diff文件,有兴趣的可以去了解一下。4种基本比较方法:
1、git diff 显示工作目录和索引(stage)的差异
2、git diff commit 显示工作目录和给定提交间的差异,其中的commit可以用HEAD(提交游标)或者用分支名代替。
3、git diff --cached commit 显示索引变更中和给定提交中变更差异。
4、git diff commit1 commit2 指定两个提交,会显示这两个之间的差异。
Git 变更提交
变更提交主要有三种方式:reset ? checkout ?revert,说一下这三种方式的不同和应用吧:
git checkout 上面提到过,用来切换不同的分支,切换完成后,当前分支和HEAD引用会变为给定分支的头。
git revert 重新创建一次新的提交提交 来撤销某一次提交,作用于全部提交,而不是文件。在使用git revert时,对提交的历史是没有影响的,而是相反往历史记录中添加新提交。
git reset 简单来说是直接回退到某次提交时的状态,具体内容比较多,所以单独写了一篇 ? 传送门
Git tag
git tag tagName // 创建tag
在使用git reset 时,可以用tag代替提交哈希id
git reset --hard tagName ?// 回滚到某一次提交
git show tagName // 查看标签详细信息
git tag -d tagName // 删除标签
给指定提交加标签
git tag -a tagName 提交哈希id
这篇就介绍这么多了,还有一些 比如:补丁、钩子、git filter-branch、结合SNV版本库使用Git,有时间会继续更新。