对于所有的开发者来说,掌握一门代码版本控制系统都是必须的,无论是自己做项目,团队合作,工作中的合作,都离不开版本控制系统的帮助。然而目前大多数初学的开发者还不了解或者还停留在几个常用的指令,那么毫无疑问是不够的。详细的了解 Git 和如何高效的使用 Git 是这篇文章要说的。
两种主要的版本控制系统
版本控制系统主要分为两个类型:集中式和分布式。相信现在还有不少的公司或团队选择的版本控制系统是 svn
,svn就是一个典型的集中事版本控制系统。而 Git 则是一个分布式版本控制系统。
什么是集中式版本控制系统
集中式版本控制系统需要一台服务器作为中央服务器,这个服务器充当我们的完整版本库,我们的其他开发者必须联网才能使用版本控制系统向我们的中央服务器提交代码和下载代码,所有开发者都是对同一个 完整版本库 进行操作。
什么是分布式版本控制系统
在分布式版本控制系统中,每一个开发者的电脑都可以作为一个完整版本库,无论是否联网开发者都可以向代码库进行提交修改等操作,通常情况下需要借助一台服务器以方便大家交换代码,所有开发者将自己的完整代码库与服务器进行同步来进行代码的交换。
分布式版本控制系统的优势
分布式版本控制系统的优势在于开发者无论是否联网,都可以进行工作,将修改提交到自己的完整版本库中。同时每个开发者都拥有这个完整版本库,所以也不必担心因中央服务器出问题而导致所以人都无法工作。而且git的分支切换等操作是基于指针位置的移动,所以性能高。
Git 代码库的分区
在本地文件夹下初始化一个git仓库后,这个仓库存在三个分区:工作区,索引区和数据库。
- 工作区: 是我们实际操作的区域,也就是说,我们开发时,看到的都是工作区的代码,任何的修改都是对工作区的直接修改。
- 数据库: 则是我们的完整版本库,它保存我们对代码的最终修改,也是代码最终的结果。
- 索引区:工作区和数据库之间存在着一个索引区,它是为了向数据库提交作准备的区域。
基本的操作
初始化仓库:
git init
将工作区的修改添加到索引区:
git add <filename>
将修改的文件添加到索引区,可以通过通配符 “*” ,或“.”来进行批量的操作:
git add file1 file2 file3 // 将指定的多个修改文件添加到索引区
git add *.txt // 将所有txt文件添加到索引区
git add . // 将所有的文件添加到索引区
将索引区中的内容添加到数据库
git commit -m "本次提交的信息"
这样我们就完成了一次完整的修改和提交。
status 和 log
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
可以查看当前的状态,比如处于哪一个分支,是否有修改未提交,哪些文件被修改了等等的信息。
git log
可以查看到目前为止的所有的提交记录,它会显示每一个提交的用户、时间、提交信息。
分支(branches)
在 Git 中分支的本质其实是一个指向最新提交的指针,创建不同的分支实际就是创建了多个指针。每一个分支互不影响,可以平行的进行开发,负责不同的任务。
创建新分支,比如新建名为test的分支:
git branch test
切换分支,进入test分支:
git checkout test
合并分支,在master分支中将test分支的修改合并进来:
// 在master分支中
git merge test
删除分支test
git branch -d test
远程仓库
克隆与关联
前面提到了所有开发者将自己的完整代码库与远程仓库进行同步来进行团队合作开发,
通过以下命令克隆或者说下载远程仓库到自己的电脑:
git clone [repository url]
克隆后可以得到一个与远程仓库关联的本地仓库。也可以通过以下命令来直接关联远程仓库:
// 将指定地址的远程数据库关联,并命名为origin
git remote add origin [repository url]
显示远端数据库列表,如:
$ git remote
origin
推送内容与分支修改
向远程仓库推送修改,比如将本地master分支代码推送到远程仓库的master分支:
git push -u origin master
第一次提交的时候通常带上参数 -u
,它的作用是记录这次操作的远程仓库地址等信息。那么我们使用例如 git pull 等命令时后面就不需要再加上对于的分支地址了。不是第一次提交的话可以省略 -u
。
删除本地某分支后,同步远程数据库,删除远程数据库上的此分支:
git push origin --delete <分支名称>
想将标签也推送到远程数据库:
git push origin --tags
拉取内容与分支修改
将远程仓库分支的最新变化拉去下来,并合并到自己的代码中:
git pull origin <远程仓库分支名称>
默认情况下,git pull 不会同步远程数据库删除的分支,加上参数-p
可以在本地删除远程数据库中已经删除的分支:
git pull -p
将远程的数据库的变化提取下来查看,但不合并到当前自己的代码中:
git fetch <远程数据库名称> <分支>
这样会将远端的变化提取到本地,在本地可以通过切换到"远程数据库/分支"来进行查看,比如查看远端master分支的修改:
git checkout origin/master
可以通过git branch指令与队友参数查看所有分支:
// 查看本地和远程所有分支
$ git branch -a
* master
remotes/origin/master
// 查看远程所有分支
$ git branch -r
origin/master
标签操作
标签分为两种:
- 轻量标签
- 注解标签
轻量标签通常作为临时标签方便我们的开发,注解标签通常为上线的代码标记版本信息,可以通过以下指令创建一个轻量标签:
git tag <标签名称>
还可以给标签添加信息备注来创建一个注解标签
git tag -a <标签名称> -m "备注信息"
// 比如:
git tag -a v1.0 -m "first version"
可以通过以下指令查看已有标签:
$ git tag
v1.0
加上参数 -n
可以连备注一起查看:
$ git tag -n
v1.0 first version
删除分支:
git tag -d <分支名称>
实际开发中运用标签
我们想查看某个标签的内容:
git checkout <标签名称>
这样就可以进入到当前分支中的对应标签中,但是这只能查看标签的内容。
如果你想基于该标签继续进行开发,那么应该先基于该标签新建一个分支,在新分支上进行开发,然后再合并。
git branch <分支名称> <标签名称>
这样就可以基于某一版本并行的开发。
进阶操作
覆盖或修改最近的提交
有时候我们想要用当前的提交去覆盖上一次的提交,避免提交历史中存在多余的提交历史,我们可以使用 --amend
参数:
git add <文件名>
git commit --amend -m "新的commit备注"
通过
git log
查看提交记录可以发现此次提交替代了上一次的提交。
取消上一次的提交(版本回退)
有时候我们需要取消上一次的提交,那么我们可以通过 reset 指令修改 HEAD 指向的位置来实现:
git reset --hard HEAD~
// ~的数量表示取消提交的数量,如果要取消强两次提交的话可以改为 HEAD~~
可以通过查看文件内容或查看git日志的方式来查看是否成功取消了修改。
这里的hard
模式的意思是:索引区和工作去都会受到影响,回退到对应的内容。除此之外还有其他的模式:
- --soft:仅HEAD的指向退回到对应位置,索引区和工作区内容不变。
- --mixed:HEAD位置和索引区内容发送改变,工作区不变。
- --hard: HEAD位置和索引区和工作区内容都发送改变。
版本恢复
如果我们版本回退后后悔了想恢复到最新版本怎么办?可以通过commit id来进行移动。
git reset --hard <对应的 commit -id>
如果我们没有记住对应的 commit id 怎么办?可以通过 git reflog 指令来查看命令历史。
$ git reflog
9154108 (tag: v1.1, tag: v1.0, origin/master, master) HEAD@{12}: pull: Fast-forward
1319463 HEAD@{13}: checkout: moving from 9154108ced0df7f7c220bc5440af008aff330e92 to master
9154108 (tag: v1.1, tag: v1.0, origin/master, master) HEAD@{14}: checkout: moving from master to origin/master
1319463 HEAD@{15}: commit (initial): first commit
这样就可以看到每次提交操作对应的 id(第一列) 了,那么我们想移动到哪个版本都可以了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。