git是开源的分布式文件管理系统
为什么说是分布式呢?简单来说就是除了集中式版本库,在各个开发本地也保存一份版本库。
这样带来了很多的优点,近乎所有操作都是本地执行,因此速度相当的快,也可以在离线时进行操作。
在Git的基础上衍生出GitHub和GitLab这两个非常流行的代码托管平台,很多公司包括阿里云、去哪儿、携程等都在GitLab平台的基础上做自己的二次开发。
https://git-scm.com/book/zh/v2为pro git的中文地址,讲解的非常好。
http://gitready.com/也是一个不错的git网站,针对常用场景写了很多短小但很优秀的博客。
Git的存储方式
Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流。
每次提交,会生成一个commit对象指向一个tree对象(提交时所有文件的一个快照);tree按文件夹的结构来排列,每个文件夹又是一个tree,每个文件指向一个blob对象。注意blob对象和文件并不完全等价,Git认为即使文件名不同只要文件内容相同就是同一个blob,这样节省了存储空间。
Git 中所有的数据在存储前都计算校验和,即 SHA-1 散列(hash,哈希), 这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。
git配置
git安装方式
git --version
查看版本
git config --global user.name yushengjun
设置全局用户名
git config --global user.email xxx@163.com
设置全局邮箱
git config --global --list
查看global下git的所有配置
git config --global color.ui auto
让命令更具可读性
git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
设置git的默认文本编辑器,这个还是挺有用的,毕竟命令行的编辑不好用
git常用操作
图中index是按照git的术语称为索引,但是一般还是叫暂存区,staging,用来存储下次要commit的文件。
1. 获取或创建git仓库
- 在本地目录初始化 Git 仓库
git init
把已有的项目代码纳入Git管理。git init your_project
会在当前路径下创建和项目名称同名的文件夹 - 从其它服务器克隆已存在的仓库
git clone https://github.com/libgit2/libgit2
http、https、ssh都是使用的智能协议。
2.提交
git add readme.txt
git commit readme.txt -m '提交readme文件'
git status
git status -s
git add 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。 将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。
git status
用来查看文件的状态。
在 Changes not staged for commit
这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区;
在 Changes to be committed
这行下面的,就说明是已暂存状态,还没提交到本地仓库
Untracked files
下面是没有被跟踪的文件。
使用 git status -s
命令,你将得到一种格式更为紧凑的输出, 输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。
3.比较工作区、暂存区、本地仓库之间的差异
git diff
是比较工作区和暂存区之间的差异,亦可以比较要指定的文件
git diff --cached
比较暂存区和本地仓库之间的差异(因此文件必须先加到暂存区)
git diff temp master -- 1.txt
比较1.txt这个文件temp分支和master分支最新一次提交之间的差异。其实这里分支也指向提交,所以我们也可以比较不同commit之间的差异(换成commit的唯一标识值即可)。
git diff HEAD HEAD~2 -- 1.txt
比较1.txt和前两次提交时的不同
4.移除文件
删除文件git rm
,然后提交即可。 如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f
当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件添加到暂存区时
git rm --cached README
把文件从 Git 仓库中删除(也从暂存区域移除),但仍然保留在当前工作目录中
git mv file_from file_to
重命名文件
5.查看提交日志
git log
查看本地提交历史
git log --oneline --all -n4 --graph --decorate
oneline简略显示提交历史,all查看所有分支 ,n4最近4次的提交历史 graph 图形化查看
gitk
打开图形化工具,推荐使用sourceTree或idea自带的
git log -S function_name
可以显示那些添加或删除了该方法的提交。
git log -p file
可以查看指定文件每次提交前后的修改内容。还可以指定目录查看指定目录下的提交历史
git log其实提供了非常丰富的日志查询参数,一下是记不住的,用到时积极查阅,才能得心应手。
下面是要在 Git 源码库中查看 Junio Hamano 在 2008 年 10 月其间, 除了合并提交之外的哪一个提交修改了测试文件,可以使用下面的命令:
$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
--before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch
6.撤销操作
我们有时想回退版本,怎么办呢?可以使用reset命令,来移动head指针,变更本地仓库的版本。
这里有三个参数,–soft --hard --mixed
git reset <commitId> --soft -- 2.txt 1.txt
变更本地仓库版本。工作区和暂存区不做变动git reset <commitId> -- 2.txt 1.txt
变更本地仓库版本和暂存区,不变更工作区。不加参数就是默认mixedgit reset <commitId> --hard -- 2.txt 1.txt
变更本地仓库版本、暂存区和工作区。(注意这个命令十分危险,会丢失你在工作区做的变更!!)
commitId指的是某次提交记录,使用git reflog
查看所有提交历史,可以方便的查找提交记录进行版本的回退和前进。
将commitId换成head,可以实现另一些常用的功能:
-
我们有时取消刚暂存的文件,怎么办呢?
git reset head -- 2.txt 1.txt
把2.txt和1.txt恢复成head,也可以不指定文件即复原所有文件 -
如果想暂存区和工作区都恢复成最新一次提交的内容该怎么办呢?
git reset --hard HEAD
将暂存区和工作区都恢复成最新一次提交的内容。 回退到上上个版本git reset --hard HEAD^^
,直到HEAD~100
。(注意这个命令十分危险,会丢失你在工作区做的变更!!) -
如果我们想恢复工作区的内容和暂存区一样,怎么操作呢?使用checkout
git checkout -- 3.txt
丢弃工作区的修改,恢复和暂存区一样。(注意这个命令比较危险,会丢失你在工作区做的变更!!)
记住,在 Git 中任何已提交的东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复 (数据恢复)。 然而,任何你未提交的东西丢失后很可能再也找不到了。
7.远程仓库的使用
git remote <-v>
查看本地配置的远程仓库信息
git remote show <remote>
查看某一个远程仓库的更多信息
git remote add origin git@github.com:xxx/git_test.git
在本地添加远程仓库,并指定缩写origin来指代远程仓库,git clone默认是origin
git fetch <remote>
将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作
git pull
自动抓取后合并该远程分支到当前分支
git push <remote> <branch>
推送到远程服务器
8. 分支的管理
git里的分支非常简单,其实就是创建个指针指向提交对象,head也是个指针指向当前分支。创建、切换、合并、删除分支都是很常见的操作。
-
创建、切换分支
git branch testing
创建分支
git checkout testing
切换分支,注意切换的时候要保证本地的修改已经提交或stash,不然会切换失败,这是git为了防止丢失你当前工作区的修改
git checkout -b testing
创建分支并切换过去,相当于上面两个命令的合并git log --oneline --decorate --graph --all
查看当前分支情况git merge testing
把testing的修改合并到当前分支,如果没有分叉就是快进(fast-forward)。如果有分叉且冲突了需要解决冲突,git add 表示冲突已解决,准备提交了,要记得提交! -
删除分支
git branch -d hotfix
删除分支,如果hotfix分支的代码已经合并到该分支,会成功删除。否则会删除失败,强制删除使用-D,这也是git为了防止你丢失hotfix的修改
git branch --merged
查看已经合并到当前分支的分支。此命令下没有*号的分支都是可以删除的,因为修改已经合并到当前分支,不会丢失任何东西
git branch --no-merged
查看有修改还没合并到当前分支的分支信息。这是-d删除分支就会失败 -
远程分支
git branch <-vv>
查看分支信息,和当前所处分支
git fetch origin --all
获取远程仓库的信息
git push <remote> <branch>
把本地新创建的分支推送到远程服务器上
git checkout -b serverfix origin/serverfix
从远程服务器上拉取serverfix 分支到本地 ,这个命令很常用,所以有快捷方式git checkout --track origin/serverfix
,甚至git checkout serverfix
即可
git branch -u origin/serverfix
让本地分支跟踪远程分支
git push origin --delete serverfix
删除远程分支
9. 标签
git tag
列出标签
git tag --list '*1.0'
搜索1.0结尾的标签
git show v1.4
可以查看这个标签的信息
Git 支持两种标签:
轻量标签(lightweight)很像一个不会改变的分支——它只是某个特定提交的引用。
附注标签(annotated) 是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。
git tag -a v1.4 -m "my version 1.4"
附注标签必须带上-a ,而且必须输入一条备注信息。轻量标签直接git tag v1.0
即可
git tag -a v1.2 9fceb02
在之前的某次提前打上标签
git push origin <tagname>
默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上