Git核心概念与基础命令
简介
Git是一个开源的分布式版本控制系统。
什么是版本控制系统?
举个例子:
当你的代码功能已经实现之后,你突然又有一个新的想法想要尝试一下,你又担心在将来新的想法没写好,原本已经写好的代码又无法恢复,这个时候该怎么办?
没有版本控制系统之前,你可以将原来的代码拷贝一份副本,在新的副本上尝试新的想法。当你又有新想法的时候,再拷贝一个副本,于是你的项目就变成了这个样子:
过了很久,你想找回你之前实现的某一个功能,但是已经不记得具体是放在哪一个副本当中了,只能一个个的项目去查找,特别麻烦。
更为麻烦的是,当你和你的同事共同去开发一个项目的时候,你们可能得通过U盘,网络文件传输等方式来同步代码,每次修改的时候还得非常注意,不然一不小心就与同事已经实现或者正在实现的功能冲突了,效率特别低下。
有了版本控制系统之后,以上的麻烦就都没有了,版本控制系统不但能自动记录每次文件的改动,还可以让同事协作编程,每次版本的更新都会有相应的记录,让你清晰地了解每个版本发生的变更信息,与同事协作的时候,也不用将项目文件传来传去,直接通过版本控制系统来进行远程同步就好了。
核心概念
工作区
工作区的内容就是你在电脑里能看到的内容,对应着本地文件。
版本库
工作区有一个隐藏目录.git,里面存放的是版本库的内容。
暂存区
一般存放在.git目录下的index文件(.git/index)中,暂存区有时也称为索引(index)。
暂存区属于版本库的一部分。
- 左侧为工作区,右侧为版本库。版本库中标记为
index的区域是暂存区,标记为master的是目录树。 - 工作区主要对应电脑中我们看到的文件。
- 版本库包含三大部分:
index、master和objects HEAD是一个指向master的指针,图中的命令中出现HEAD的地方都可以用master来替换。objects是Git的对象库,位于.git/objects目录下,里面包含了创建的各种对象及内容。
工作流程
- 当我们添加或修改了一个文件之后,执行
git add命令,将文件从工作区添加到暂存区中。暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。 - 添加到暂存区之后,执行
git commit命令,将暂存区的目录树写到版本库中,master分支会做对应的更新。即master指向的目录树就是提交时暂存区的目录树。 git reset HEAD可以撤销一次提交,保留工作目录,并且清空暂存区。也就是说,工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。git rm --cached <file>命令可以从暂存区删除文件,工作区则不做出改变。git checkout .或者git checkout -- <file>命令会将工作区的文件替换成暂存区的文件。因为会清除工作区中未添加到暂存区的改动,所以有丢失代码的危险。git checkout HEAD .或者git checkout HEAD <file>命令会将工作区和暂存区中的文件替换成HEAD指向的master分支中的文件。因为会清楚工作区和暂存区中未提交的改动,所有具有更高的危险性。
基本操作
说明:
- workspace:工作区
- staging area:暂存区/缓存区
- local repository:版本库或本地仓库
- remote repository:远程仓库
# 初始化仓库
$ git init
# 添加文件到暂存区
$ git add .
# 将暂存区的内容添加到仓库
$ git commit
创建仓库命令
# 初始化仓库
$ git init
# 下载一份远程仓库项目
$ git clone <url>
提交与修改
# 添加文件到暂存区
$ git add
# 查看仓库状态,显示有变更的文件,-s获得简短的输出结果
$ git status
# 比较工作区和暂存区中文件的差异
# --cached或者--staged显示暂存区中与上一次commit的差异
$ git diff <file>
# 提交暂存区到版本库
# -a参数设置修改文件后不需要git add命令,直接提交
$ git commit -m <message>
# 设置提交时的用户信息,去掉--global参数只对当前仓库有效
$ git config --global user.name 'jiafu'
$ git config --global user.email hello@world.com
# 回退版本
# --mixed为默认,用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变
# --soft用于回退到某个版本
# --hard参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交
$ git reset [--soft | --mixed | --hard] [HEAD]
# 删除工作区和暂存区的文件
$ git rm <file>
# 仅删除暂存区的文件,而保留工作区的文件
$ git rm --cached <file>
# 移动或重命名工作区的文件
$ git mv <file>
关于git reset中HEAD的说明:
- HEAD 表示当前版本
- HEAD^ 上一个版本
- HEAD^^ 上上一个版本
- HEAD^^^ 上上上一个版本
- 以此类推...
可以使用 ~数字表示
- HEAD~0 表示当前版本
- HEAD~1 上一个版本
- HEAD^2 上上一个版本
- HEAD^3 上上上一个版本
- 以此类推...
分支管理
# 查看分支
$ git branch
# 创建分支
$ git branch <branch name>
# 删除分支
$ git branch -d <branch name>
# 切换分支
$ git checkout <branch name>
# 合并分支,将目标分支合并到当前分支
$ git merge <branch name>
提交日志
# 查看历史提交记录
# --oneline以简洁的形式
# --graph开启拓扑图形式
# --reverse逆向显示
# --author=<author name>查找指定用户的日志
# 更多参数:http://git-scm.com/docs/git-log
$ git log
# 以列表形式查看指定文件的历史修改记录
$ git blame <file>
远程操作
# 远程仓库操作
$ git remote
# 从远程获取代码库
$ git fetch
# 下载远程代码并合并
$ git pull
# 上传远程代码并合并
$ git push
与SVN的区别
- Git是分布式的,SVN不是
- Git把内容按元数据方式存储,而SVN是按文件
- Git分支和SVN分支不同,SVN中的分支就是版本库中的另外一个文件夹
- Git没有一个全局的版本号,而SVN有
- Git的内容完整性优于SVN