Git
保存的不是文件差异或者变化量,而是一系列文件快照
三种状态
已提交(committed): 该文件已经被安全的保存在本地数据库中
已修改(modified):修改了某个文件,但是没有提交保存
已暂存(staged):已修改的文件放在下次提交时要保存的清单中
Git配置
# 1. 配置个人信息
git config --global user.name "iFan"
git config --global user.email iFan@example.com
# 2. 配置文本编辑器
git config --global merge.tool vimdiff
# 3. 配置差异分析工具
git config --global merge.tool vimdiff
# 4. 查看配置信息
git config --list
仓库配置
# 1. 初始化Git仓库
git init
# 2. 添加文件
git add .
git add Readme
git add *.c
# 3. 提交
git commit -m 'init project'
添加忽略文件 .gitignore
查看仓库的状态 git status
查看文件差异 git diff
删除记录的文件 git rm file
文件改名 git mv old_file new_file
查看日志
# 查看日志
git log
# -p 展开显示每次提交的内容差异
# -2 仅显示最近两次更新
git log --p -2
# --stat 仅显示简要的增改行数统计
git log --stat
# --pretty 可以指定使用完全不同于默认格式的方式展示提交历史
# online 将每个提交放在一行显示
# short full fuller
git log --pretty=online
# 格式化信息
# 选项 占位符说明
# %H 提交对象的完整哈希字符串
# %h 提交对象的简短哈希字符串
# %T 树对象(tree)的完整哈希字串
# %t 树对象的简短哈希字串
# %P 父对象(parent)的完整哈希字串
# %p 父对象的简短哈希字串
# %an 作者(author)的名字
# %ae 作者的电子邮件地址
# %ad 作者修订日期(可以用 -date= 选项定制格式)
# %ar 作者修订日期,按多久以前的方式显示
# %cn 提交者(committer)的名字
# %ce 提交者的电子邮件地址
# %cd 提交日期
# %cr 提交日期,按多久以前的方式显示
# %s 提交说明
git log --pretty=format:"%h - %an, %ar : %s"
# 使用online或format时结合--graph选项
git log --pretty=format:"%h %s" --graph
# 查看指定时间的提交
# 选项 说明
# -(n) 仅显示最近的 n 条提交
# --since, --after 仅显示指定时间之后的提交。
# --until, --before 仅显示指定时间之前的提交。
# --author 仅显示指定作者相关的提交。
# --committer 仅显示指定提交者相关的提交。
git log --pretty="%h:%s" --author=gitster --since="2008-10-01" --before="2008-11-01" --no-merges --t
撤销操作
# 撤销最后一次提交
git commit --amend
# 撤销提交,添加文件,再次提交
git commit -m 'initial commit'
git add file
git commit --amend
# 取消暂存文件
git reset HEAD file
远程仓库
# 下载
git clone url
# 列出远程仓库地址
git remote -v
# 添加远程仓库
git remote add remote-name url
# 拉取指定仓库信息,不合并
git fetch remote-name
# 拉取并合并
git pull
# 提交到远程仓库
git push [remote-name] [branch-name]
# 查看远程仓库的信息
git remote show origin
# 删除远程仓库
git remote rm remote-name
标签
# 查看标签
git tag
git tag -l 'v.1.*'
git show v.1.2
# 新建标签
git tag -a v.1.2 -m 'version 1.2'
git tag v.1.3
git tag -a v.1.4 提交对象的验证和
# 传送到远程仓库
git push origin [tagname] # 传送指定
git push origin --tags # 传送所有
分支
# 查看分支
git branch -v
# 新建分支
git branch branch-name
# 切换分支
git checkout branch-name
git checkout -b branch-name # 新建并切换到该分支
# 分支合并到master
git checkout master
git merge branch-name
# 删除
git branch -d branch-name
git branch -D branch-name # 强制删除
git branch --merged # 已经被并入到当前分支
git branch --no-merged # 没有被并入到当前分支
# 推送分支到远程仓库
git push remote-name local-branch-name:branch-bane
# 检出远程仓库的分支到本地
git checkout -b local-branck-name remote-name/branch-name
# 跟踪远程仓库
git checkout --track remote-name/branch-name
# 删除远程分支
git push remote-name :branch-name
# 衍合
# !!! 永远不要衍合那些已经推送到公公仓库的更新
# 回到两个分支的共同祖先,提取所在分支每次提交时产生的差异,把这些差异分别保存在临时文件中,然后从当前分支转换到需要衍合入的分支,依序施用每一个差异补丁文件。最后整合的结果没有任何区别,但衍合能产生一个更为整洁的提交历史。
git checkout branch-name
git rebase master
小工具
全局更换电子邮件地址
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
查看父提交
# ^表示第一个父提交
git show HEAD^
# 第一个父提交的第一个父提交
git show HEAD^^
# 第二个父提交
git show HEAD^2
储藏(Stashing)
获取工作目录的中间状态,将其保存到一个未完结变更的堆栈中,随时可以重新应用。
# 向堆栈中推送一个存储
# 可以在运行命令之前和之后使用 git status 查看
git stash
# 查看现有存储
git stash list
# 应用存储
git stash apply
git stash apply stash@2
git stash apply --index # 重新应用被暂存的文章
Git 内部原理
Git是一套内容寻址文件系统,在此之上提供了一个VCS用户界面
Git中存在三个对象,分别是tree,commit,blob对象,分别存储目录树,提交信息,文件对象。
commit对象格式很简单:指明了该时间点项目快照的顶层树对象、作者/提交者信息以及当前时间戳、一个空行、以及提交注解信息。
为每份内容生成一个文件,取得该内容与头信息的SHA-1校验和,创建以该校验和前两个字符为名称的子目录,并以剩下的38个字符为文件名(保存至子目录下)
生成 -> git cat hash-object -w filename
解析 -> git cat-file -p 校验码
这些对象信息存储在.git/objects下
在.git/refs下存储了文件的引用信息,包含分支,master等
.git/HEAD中存储了最后一次提交的SHA-1值
git往磁盘保存对象时默认使用的格式叫松散对象格式,不定时将这些对象打包至一个叫packfile的二进制文件以节省空间并提高效率,当仓库中有太多的松散对象、手工调用git gc命令或者推送至元亨服务器时,Git都会这样做。
git会不定时的自动运行称为auto gc的命令,大部分情况下该命令什么都不处理,存在太多松散对象或packfile(7000的左右的松散对象或者50个以上的packfile),git会进行调用git gc命令,收集所有松散对象并将他们存储packfile,合并packfile进一个大的packfile,然后将不被任何commit引用并且已经存在一段时间(数月)的对象删除。