about git

Posted by ZhouJ000 on June 30, 2018
最后更新于:2018-06-30

about svn

周一参加了公司的GIT分享,对几个自己不太用到的命令有了些认识,练习了一波后,写一个关于git命令的自我总结。

GIT基础知识

SHA

所有用来表示项目历史信息的文件,是通过一个40个字符的(40-digit)“对象名”来索引的。每一个“对象名”都是对“对象”内容做SHA1哈希计算得来的,(SHA1是一种密码学的哈希算法)。这样就意味着两个不同内容的对象不可能有相同的“对象名”。

对象

每个对象(object) 包括三个部分:类型,大小和内容。大小就是指内容的大小,内容取决于对象的类型,有四种类型的对象:”blob”、”tree”、 “commit” 和”tag”。

目录结构

$>tree -L 1
.
|-- HEAD         # 这个git项目当前处在哪个分支里
|-- config       # 项目的配置信息,git config命令会改动它
|-- description  # 项目的描述信息
|-- hooks/       # 系统默认钩子脚本目录
|-- index        # 索引文件
|-- logs/        # 各个refs的历史信息
|-- objects/     # Git本地仓库的所有对象 (commits, trees, blobs, tags)
`-- refs/        # 标识你项目里的每个分支指向了哪个提交(commit)。

工作区域

git space

GIT命令

初始化

设置名称与email:

git config [--global] user.name "xxx"
git config [--global] user.email "xxx@gmail.com"
会在你的主目录(home directory)下的 ~/.gitconfig 文件增加一节[user]内容。
不带 --global 选项来设置. 这会在你项目目录下的 .git/config 文件增加一节[user]内容

常用命令

工作中常用:

  • 初始
    • git clone [http/git]: clone一个仓库
    • git init: 初始化一个新的仓库
  • 分支
    • git branch [-a]: 查看分支
    • git checkout xxx: 切换分支
    • git checkout -b xxx: 创建新分支并切换到新分支
    • git branch -d/-D: 删除本地分支(强制删除)
    • git push –delete origin xxx: 删除远程分支
  • 提交
    • git pull [origin xxx]: 拉取并合并远程分支新的提交,相当于fetch+merge
    • git stash [“sth.”]: 储藏当前的工作状态
    • git stash pop/apply [stash@{1}]: 恢复到以前的工作状态
    • git add .: 添加全部更新到索引中(暂存区)
    • git merge xxx: 合并分支xxx到当前分支
    • git status: 查看索引,看哪些文件被暂存了(就是在你的Git索引中), 哪些文件被修改了但是没有暂存, 还有哪些文件没有被跟踪(untracked)
    • git commit -[a]m ‘sth.’: 提交全部更新
    • git push [origin master]: 提交本地提交到远程分支
    • git log [–stat]: 查看提交记录(显示每个提交中哪些文件被修改了)
  • 撤销
    • git reset –hard [HEAD/ORIG_HEAD]: 工作区回到上次提交时的状态
    • git reset ./HEAD file: 暂存区被重置(丢弃),但是工作区文件不变
    • git checkout ./– file: 工作区被重置(丢弃)
    • git clean -df[x]: 清空未跟踪的修改
  • 忽略:
    • .gitignore文件

偶尔会用的:

  • git fetch: 拉取更新,更新分支信息
  • git diff HEAD [xxx]: 查看修改的内容差异,一般使用IDE插件或GIT工具(source tree)查看
  • git diff –cached: 比较暂存区和版本库差异
  • git remote [-v]: 查看库
  • git remote add origin2 xxxxx: 新增库别名与对应的URL
  • git remote set-url origin xxxxx: 修改库别名对应的URL(fetch/pull)
  • git tag [对象名]: 标签
  • git config -l: 查看所有配置
  • git rm [--cached]: 从版本库中删除文件/从版本库中删除文件,但不删除文件

新学到的

git rebase

平时使用的merge命令会有一个合并的新节点,两条分支交汇于一点。

使用rebase会让被合并的分支历史看起来像没有被合并过一样:

git checkout mywork
git rebase origin

遇到冲突时,解决冲突,然后
git add 更新
git rebase --continue 继续rebase,或
git rebase --abort 终止rebase

rebase

交互式rebase

交互式rebase提供了一个简单易用的途径让你在和别人分享提交之前对你的提交进行分割、合并或者重排序。

git rebase -i master


pick 08acb40 D
pick 1b77f35 E
pick 7242c9c F
# Rebase 6b36f5a..7242c9c onto 6b36f5a (3 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

行格式: (action) (partial-sha) (short commit message)

修改action,比如后2个修改为'squash'操作,git会把这个提交和前一个提交合并成为一个新的提交。
解决冲突,完成后查看git log发现只有1个提交记录,且在同一条树状结构上

git cherry-pick

从不同的分支中捡出单独的commit,并把它和你当前的分支合并。

git cherry-pick (commitid1..commitid100]
git cherry-pick commitid

cherry-pick不但可以用在不同分支之间,也可以用在同一个分支上。

git revert

创建了一个撤消了上次提交(HEAD)的新提交, 你就有机会来修改新提交(new commit)里的提交注释信息

git revert HEAD
git revert commitid

git revert 其实不会直接创建一个提交(commit), 把撤消后的文件内容放到索引(index)里,你需要再执行git commit命令,它们才会成为真正的提交(commit)。将需要revert的版本的内容再反向修改回去。 git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

其他

日志的格式化,排序,按树图展示,可以在脚本中获取所需信息做一些操作

git log --pretty=format:'%h : %s' --topo-order --graph

交互式添加提供友好的界面去操作Git索引(index),同时亦提供了可视化索引的能力。

git add -i

*** Commands ***
  1: status       2: update       3: revert       4: add untracked
  5: patch        6: diff         7: quit         8: help

分支, Remote 或 标签

你可以使用分支,remote或标签名来代替SHA串名, 它们只是指向某个对象的指针. 假设你的master分支目前在提交(commit):’980e3’上, 现在把它推送(push)到origin上并把它命名为标签’v1.0’, 那么下面的串都会被git视为等价的:

980e3ccdaac54a0d4de358f3fe5d718027d96aae
origin/master
refs/remotes/origin/master
master
refs/heads/master
v1.0
refs/tags/v1.0

搜索关键词

git grep [-n][-c] keyword [tag reference]

git grep -e '#define' --and -e SORT_DIRENT
git grep --all-match -e '#define' -e SORT_DIRENT
git grep -e '#define' --and \( -e PATH -e MAX \) 

标识符

日期标识符:
master@{yesterday} master@{1 month ago}

顺序标识符:
master@{5}

多个父对象:
master^2

第N级嫡(祖)父对象:
master~2 master^^

树对象指针:
master^{tree}

二进制标识符: master:/path/to/file

区间: 7b593b5..51bea1 7b593b..

维护Git

git靠压缩历史信息来节约磁盘和内存空间 git gc

查找修改

查看文件的每个部分是谁修改的: git blame -L 1,+10 test.txt

Git Bisect

二分查找, 确定问题版本

1. 进行搜索
git bisect start 

2. 告诉git当前版本是坏的
git bisect bad [xxxxxx]

3. 告诉git一个好的版本
git bisect good xxxxxx
这样git就会给你选择一个中间版本, 然后你再进行测试,确认是好的版本 OR 坏的版本。 以此类推,很快锁定 问题发生的版本。

4. 直到定位到出错的 commit,退出 bisect
git show
git bisect reset

Git Hooks

Git补丁管理(方便在多台机器上开发同步时用)

生成补丁
git diff > ../sync.patch 

打补丁
git apply ../sync.patch

测试补丁能否成功
git apply --check ../sync.patch