QuietHeart's Site

Git学习笔记


目录

1 简介

2 基本

2.1 初始化操作 git init

2.1.1 基本语法

git init [-q | --quiet] [--bare] [--template=<template_directory>] [--separate-git-dir <git dir>] [--shared[=<permissions>]] [directory]

2.1.2 常用操作

  • 创建纯库

    输入 $git init --bare

    这样会创建一个git库,只有库的内容,没有 .git 目录(也就是说只创建一个库,这个库中没有工作代码,只供别的人工作 git clone 用,如果没有 --bare 那么创建的目录中包含一个 .git 目录, .git 目录的内容是库内容)。实践发现,分别用两个目录同样的内容用 git init 创建库,两个库是不同的库,就算提交注释一样,文件目录一样,其commit id也不一样。但是, git clone 出来其中一个库之后,可以在clone的库中将 .git/config 中的源改成另外一个库,并且 git pull 。所以,假设我们在机器A上 git init --bare ,在机器B上 git init 并且提交了代码,将A添加到B的 remote 中,在B进行 git push ,这样机器A中之前的空库就有了B的提交内容。

  • 创建共享库

    输入 $git init --share

    创建的git库可以被人共享。

2.2 克隆操作 git clone

2.2.1 常用操作

  • 复制库到本地

    输入 $git clone xxx

    这样会将 xxx 所指向的git库复制一份到本地。复制之后,本地包含两个部分:

    1. .git 目录中包含库信息。
    2. .git 外面的工作区。

    其实 .git 就包含了所有的内容,我们传输文件时只需要目录中有一个 .git 目录,然后 git reset --hard 就可恢复出head对应的工作区内容。

    注意,这里复制的库用 git branch 看不到远端(来源)的分支信息,想看远端的分支信息用 git branch -a 。详见 git branch 相关命令。

  • 复制裸库,不含工作区

    输入 git clone --bare

    这里,我们使用 git clone --bareclone 其中的 .git 目录,其余内容可以用 git reset --hard 在本地还原。对于本地的 git clone ,其实默认做的是硬链接,速度很快。对本地源库使用 git clone --bare xxx 可以发现 .git 会瞬间将 xxx 直接 clone 到当前目标目录的 .git 形成裸库,通过 git reset --hard 恢复其内容。

2.3 分支操作 git branch

2.3.1 基本语法

git branch [--color[=<when>] | --no-color] [-r | -a] [--list] [-v [--abbrev=<length> | --no-abbrev]] [(--merged | --no-merged | --contains) [<commit>]] [<pattern>...]
git branch [--set-upstream | --track | --no-track] [-l] [-f] <branchname> [<start-point>]
git branch (-m | -M) [<oldbranch>] <newbranch>
git branch (-d | -D) [-r] <branchname>...
git branch --edit-description [<branchname>]

2.3.2 NEXT 常用操作

  • State "NEXT" from [2016-03-04 五 17:16]

*查看本地分支: $git branch 会输出本地分支,如: test *master 这表示有一个master主分支,和test分支。master是默认的分支,当前所处分支用'*'标记,在master上。对于如何存储,可参见:.git/refs/head/<分支名>。

*查看远端分支: $git branch -r 会输出远端(可能是多个远端)的分支,如: cognac/master origin/albert 这里,'/'前面是远端名,'/'后面是实际的分支。对于如何存储,可参见:.git/refs/remotes/<远端分支名>。

*查看本地和远端分支: $git branch -a 同时查看远端和本地分支,远端分支以红色显示。 一般git clone之后,如果只用"git branch"则只能看到远端当前的分支,使用这个命令可以看到远端其他的分支,可以切换至这个分支,但如果想在其中进行工作,需要基于此分支创建一个本地的相应分支。

*创建分支: $git branch <branch name>

*修改分支名称: $git branch -m <old name> <new name> 注意,不要有已有的分支名冲突。

*基于远端分支创建相应的本地分支: $git branch -track origin/albert 新版git不用-track选项,会根据远端分支名知道加上track选项,创建之后,相应的分支在本地创建,会与远端分支关联。这样pull会知道如何合并分支,以及获知各种其他远端跟踪的信息(如本地比远端多提交了几个版本等)。

*基于某个点创建分支: git branch <branch name> <start point> 这里,branch name就是你的分支名,start point可以是一次提交,或者一个分支名等等,标识你的当前分支是基于此进行创建(衍生)的。 关于branch是基于哪个分支创建的,目前尚无方法,可以查看.git/config中,对应branch中的merge字段,知道merge的分支。 **

**checkout分支操作 git checkout [-q] [-f] [-m] [<branch>] git checkout [-q] [-f] [-m] [[-b|-B|–orphan] <new_branch>] [<start_point>]

*开始一个无历史的新分支: $git checkout –orphan <branchname> 创建一个孤儿分支,该分支上第一个提交历史没有任何父亲节点。这样可以开始一个新分支,但是又不会把很长很长的历史记录带进来,例如,你想在公众区域(开源)放置你的代码,但是又不想别人知道它的历史记录会用到这个。一般在孤儿分支中,如果你想创建一个完全无关的内容,那么第一步往往是把当前所有文件清空,这样这个分支就和其它分支没有任何关联了。

*创建分支并切换入新创建的分支: $git checkout -b <branch name> 另外,如果是从remote获取的,本地无br1分支,那么可以用:git checkout -b br1 origin/xx/br1

*创建指定起点的分支: $git checkout -b <branch name> <start point> 这里,start point指定分支是基于谁来创建的,可以是分支名,也可以是提交名。如果没有这个参数,默认以当前分支的head为分支起点。

*创建基于<tag_xxxx>的分支: $git checkout -b my_branch <tag_xxxx> 这样,会创建一个分支,该分支基于<tag_xxxx>。 **

2.4 检出操作 git checkout

**checkout回复操作 *恢复之前的某次提交: $git checkout <commitid> 这样,会将当前的HEAD指向<commitid>所处的提交,通过'git log'可发现,执行之后,log中commitid之后的提交消失了,但是如果记住<commitid>的话,可以将之前的HEAD回复,所以要注意checkout之后log无法找到之前的最新head。

*恢复之前的某次提交的某个目录: $git checkout <commitid> – <dir> 如果文件应该不需要"–"。 **

2.5 合并操作 git merge

9.将dev1的分支merge到dev2分支 在dev2分支下,git merge –commit dev1 冲突的解决: git merge产生冲突之后: 解决相应文件冲突,删除冲突标记,最后运行git add该文件表明冲突解决。或者使用git mergetool

产生冲突时,如果是文本文件则有冲突标记,如果是二进制文件,无法确定.

假设冲突文件是liba.so, 那么目录中仍然是liba.so(并且是当前dev2的liba.so),只是git status显示bothmodified.

使用 git checkout liba.so –theirs 将会确认使用 dev1下的liba.so(此时md5值变成了dev1的), 然后 git add liba.so, git commit.

使用 git checkout liba.so –ours 将会确认使用 dev2下的 liba.so(此时md5维持dev2的), 然后 git add lib.so, git commit.

2.6 标签操作 git tag

标签管理,类似svn中的tags,用于对git中发布的重要发布点贴标签,便于以后跟踪。 *列出所有标签: $git tag

*轻量级标签: $git tag v1.4 这样为当前最新提交创建一个简单地标签。

*创建带注释的标签: $git tag -a v1.4 -m "the version 1.4."

搜索标签: $ git tag -l v1.4.2. v1.4.2.1 v1.4.2.2 v1.4.2.3 v1.4.2.4 这样可以按照特定表达式搜索已有的标签。

*为以前的提交创建一个标签: $git tag v1.1 2f5cff72102b47e7 这样会为2f5cff72102b47e7这个提交创建一个轻量级的标签。使用'git checkout'命令可以取出相应tag。

*查看标签: $git show v1.1 这样会显示是一个标签,并且显示相应的commit信息。

*删除标签: $git tag -d v1.1 这样会将v1.1的tag删除。 默认情况下,’git push’命令不会将标签上传到远程服务器上。为了共享这些标签,你必须在’git push’命令后明确添加-tags选项;git fetch会将远端tags下载。

*显示包含指定提交的tag: git tag –contains <commit id> 这里会显示所有包含commit id的tag,commit id可以省略,这时候显示包含head的tag。 **

2.7 配置操作 git config

2.7.1 列出配置内容

查看所有配置内容

$git config -l

涉及三个层级的配置文件: system 的, global 的, 以及 local 的。

system 的配置文件一般在 /etc/gitconfig,对所有用户有作用。

global 的配置文件一般在 /home/.gitconfig, 对当前用户有作用,会覆盖 system 的配置。

local 的配置文件一般在 .git/config, 对当前项目有作用,会覆盖 global 的配置。

如果只看某个层级的,只需要加上对应的 --system, --global, --local 选项即可。

比如查看 global 的配置选项

$git config --global -l

2.7.2 配置默认编辑器

配置当前项目默认编辑器为 vim

$git config core.editor vim

相当于打开 .git/config 文件,在 core 中添加 editor=vim, 只对当前 git 项目有效。这样 git commit 之后会调出 vim 编辑信息。

如果配置成全局所有 git 项目默认都为 vim 如下:

$git config --global core.editor vim

--global 表示会将配置应用到所有的 git 中,因为会保存到全局配置文件中, 而非针对当前项目的本地配置文件 .git/config 中了。

或者如果只是临时修改, 则设置 EDITOR 环境变量

$export EDITOR=vim

3 远程同步与协作

3.1 更新分支 git rebase

下面从几个方面上来理解 rebase 命令

3.1.1 只有本地库

假设历史如下,并且当前的分之为 topic

      A---B---C topic
     /
D---E---F---G master

对于这种情况,使用如下两个命令的任何一个,

$git rebase master

$git rebase master topic

这样,将会导致历史变成如下:

              A'--B'--C' topic
             /
D---E---F---G master

注意,后面的命令 $git rebase master topic 实际就是 git checkout topic + git rebase master 这两条命令的简写。当 rebase 退出的时候,当前分支保持为 topic 分支。

2.如果上游分支已经包含了你已经做过的修改(例如:你通过电子邮件发送了一个修改的补丁并且这个补丁已经应用到了upstream上面),那么那个commit将会在rebase的时候被忽略。 例如在如下的历史中运行"git rebase master"(这里的A和A'虽然是不同的commiter信息,却表示同样的修改):

A—B—C topic / D—E—A'—F master

导致的结果将是:

B'—C' topic / D—E—A'—F master

3.如果你想要将一个基于某个分支的topic分支迁移到另外一个分支,使得我们看起来这个topic是基于那个另外的分支,那么,我们使用rebase –onto。 首先,我们假设topic分支基于next分支。例如,topic分支中开发的某个功能依赖于next分支中的功能。如下:

o—o—o—o—o master \ o—o—o—o—o next \ o—o—o topic

我们想要让topic基于master分支。例如:q We want to make topic forked from branch master; for example, because the functionality on which topic depends was merged into the more stable master branch. We want our tree to look like this:

o—o—o—o—o master

\
o'–o'–o' topic

\ o—o—o—o—o next

We can get this using the following command:

git rebase –onto master next topic

3.1.2 pull

**rebase的作用 如果不进行rebase,那么使用git pull作用于已经有了提交的本地库,将会导致一个合并。rebase可以将本地修改置于pull之后,将历时简化,不会出现很多的分支。 1、对于git pull, 合并前: 4–>6 (master) / 1–>2–>3–>5 (origin/master) 相当于在远程3处调用了git clone,之后得到的本地库便具有两个分支(master表示本地主分支,origin/master表示git clone的来源分支)然后本地修改commit提交形成了本地版本4,同时远端origin/master继续前进至5,本地又也前进至6. 合并后: 4–>6 / \ 1–>2–>3–>5–>7(master,origin/master) 相当于本地运行了一次git pull命令,于是导致远程分支的5和本地的6合并,生成新版本7。pull命令的作用是,获取远端修改,再将此修改合并到本地。

2、如果我们使用git pull –rebase: 4–>6 X 1–>2–>3–>5–>4`–>6`(master,origin/master) 相当于 a.缓存master自上次pull后本地所有的更改(即->4–>6的更改),(实践发现,是第一次pull/clone相应分支的本地提交更改,哪怕之后没有–rebase过很多次的pull)。 b.退回到上次pull的状态(即将master的->4–>6更改取消,退回到3)。 c.调用git pull获取并应用远端的修改(即将master前进到5)。 d.将之前缓存的本地修改应用到新的主分支上(即将之前缓存的->4–>6更改重新作用到5上,得到->4`–>6`,结果和合并一样,但是少了一个具有两个父亲节点的7,以及分支4-6,简化了前进日志过程)。 如果rebase过程中,出现冲突,那么可根据提示,运行"git mergetool", 调用出相应的比较工具(如meld)进行冲突解决,最后git rebase –continue继续进行rebase。 rebase之后,之前缓存的->4–>6的更改,已经无用了,可以用"git gc"将其清除。

3.1.3 有冲突时

rebase产生冲突后,大致提示如下: Failed to merge in the changes. Patch failed at 0001 [TPAPI] Secure buffer player.

When you have resolved this problem run "git rebase –continue". If you would prefer to skip this patch, instead run "git rebase –skip". To check out the original branch and stop rebasing run "git rebase –abort". 通过git status可以知道哪些文件冲突了。 解决冲突后,运行git add将冲突文件添加进去(表示标记为解决冲突了),再进行git rebase –continue

具体参考: http://gitbook.liuhui998.com/4_2.html http://git-scm.com/book/zh/ch3-2.html **

4 获取当前库信息

5 FAQ [10%][2/20]

5.1 NEXT git describe

  • State "NEXT" from [2016-01-08 五 10:03]

显示当前提交对应的tag,如果当前提交没有tag,则显示当前提交基于的tag,以及tag后发生了多少次提交,以及最近提交号简写。

假设有master和jike两个branches
$ git-branch
  jike
 *  master

# master分支基于tag:v2.6.27-rc5,head相对于该tag提交了361次
[arc@localhost  linux-2.6]$ git-describe
v2.6.27-rc5-361-g82a28c7

#jike分支基于tag:v2.6.27-rc5,head相对于该tag提交了320次,比master旧
[arc@localhost  linux-2.6]$ git-checkout jike
Switched  to branch "jike"
[arc@localhost  linux-2.6]$ git-describe
v2.6.27-rc5-320-gf8a561a

参考:http://blog.csdn.net/yby19870627/article/details/7375121

5.2 NEXT git log

  • State "NEXT" from [2016-01-08 五 10:37]

5.2.1 –decorate

git log命令的–decorate参数可以在提交ID的旁边显示该提交关联的引用(里程碑或分支)

commit 1ff5d5435ef8a4bafe51ea10cc4be8be63903c2a (HEAD, tag: QM153E_R0.5.99.0, tag: QM153E_R0.5.98.0, tag: QM152E_R0.5.98.1, tag: QM152E_R0.5.98.0, tag
Author: van.huang <van.huang@tpv-tech.com>
Date:   Sat Oct 10 10:30:31 2015 +0800

    [TPAPI]Fix 2K16 U+ DVB-S TS issue.
    URTRACKER:PPR2-EU

    ::::        ::::
    Cherry Pick from 9df216d714a7ef3358b604753f223de47647a56b
    ::::                        :::

    Change-Id: Ieb360ec0ee10ecd54138b0db95d7f9c32bd34956

commit e59a4968b80b9335200053013eb6a9c774e10ef7
Author: paul.deng <paul.deng@tpv-tech.com>
Date:   Sat Oct 10 10:30:31 2015 +0800

    [TPAPI][DEMUX] Enable CRC Error Threshold Exceeded notification.
    URTRACKER:PPR2

    ::::        ::::
...

5.2.2 查看某两个tag/commit之间的log

$git log tag1 tag2

5.2.3 格式化的输出

Commit Date在 2018-06-14 以来的,作者为"miracle.lv"的,"origin/2k18_mtk_msaf_kane_n_devprod_ctv"分支上的提交信息,仅包含作者,日期,以及宽度在32以内的注释。

$git rev-list --reverse --pretty=format:"Author: %an%nCommit date: %ci%nDescription: %<(32,trunc)%s" --since=2018-06-14 --author="miracle.lv" origin/2k18_mtk_msaf_kane_n_devprod_ctv |head -n4
commit 481a592b6afb07aff347b5948acfdb444981022c
Author: Miracle Lv
Commit date: 2018-06-26 17:14:42 +0800
Description: Improve check for branch for i..

5.2.4 查看日志同时也显示具体修改的文件

$git log -p

除了显示commit id等基本信息外,还显示具体修改了文件的什么内容,结果用git diff的方式显示出来。

$git log --stat

显示commit id之外,显示修改了哪些文件以及多少行,但是不具体显示修改内容。

5.2.5 待阅

git 对比两个分支差异

查看 dev 有,而 master 中没有的:
git log dev ^master 

同理查看 master 中有,而 dev 中没有的内容:
git log master ^dev

查看 dev 中比 master 中多提交了哪些内容:
git log master..dev
注意,列出来的是两个点后边(此处即dev)多提交的内容。

不知道谁提交的多谁提交的少,单纯想知道有什么不一样:
git log dev...master

在上述情况下,再显示出每个提交是在哪个分支上:
git log --left-right dev...master
注意 commit 后面的箭头,根据我们在 –left-right dev…master 的顺序,左箭头 < 表示是 dev 的,右箭头 > 表示是 master的。

5.3 NEXT git revert

  • State "NEXT" from [2017-06-30 五 11:19]

与 概念上的revert还是不一样的,因为在多分支合并的时候revert还是有问题的,考虑用merge来模拟回退。 参考:http://blog.csdn.net/secretx/article/details/51461972

git revert <commit id> 撤销仅 <commit id> 对应的提交。不包含 <commit id> 到当前 HEAD的其他提交的撤销。

5.4 NEXT git remote

  • State "NEXT" from [2016-01-09 六 11:19]

如下:

 1 [core]
 2     repositoryformatversion = 0
 3     filemode = true
 4     bare = false
 5     logallrefupdates = true
 6     worktree = /home2/miracle.lv/wk16.1_2k16ppr1gits/device/tpvision/tvsoc/tvsoc_mtk
 7 [remote "origin"]
 8     fetch = +refs/heads/*:refs/remotes/origin/*
 9     url = /home2/miracle.lv/wk16.1_2k16ppr1gits/../2k16ppr1gits//.gits/projects/device/tpvision/tvsoc/tvsoc_mtk
10 [branch "default_head"]
11     remote = origin
12     merge = refs/heads/default_head

运行 git remote add mirror ssh://gerrit/device/tpvision/tvsoc/tvsoc_mtk 如下

 1 [core]
 2     repositoryformatversion = 0
 3     filemode = true
 4     bare = false
 5     logallrefupdates = true
 6     worktree = /home2/miracle.lv/wk16.1_2k16ppr1gits/device/tpvision/tvsoc/tvsoc_mtk
 7 [remote "origin"]
 8     fetch = +refs/heads/*:refs/remotes/origin/*
 9     url = /home2/miracle.lv/wk16.1_2k16ppr1gits/../2k16ppr1gits//.gits/projects/device/tpvision/tvsoc/tvsoc_mtk
10 [branch "default_head"]
11     remote = origin
12     merge = refs/heads/default_head
13 [remote "mirror"]
14     url = ssh://gerrit/device/tpvision/tvsoc/tvsoc_mtk
15     fetch = +refs/heads/*:refs/remotes/mirror/*

5.5 LATER git grep等搜索方式

  • State "LATER" from "INBOX" [2016-01-16 六 09:40]

Capture Time:[2016-01-11 一 10:42]


5.6 LATER git对链接文件的管理

  • State "LATER" from "INBOX" [2016-01-16 六 09:40]

Capture Time:[2016-01-11 一 11:18]


5.7 WAIT/FORWARD git commit

  • State "WAIT/FORWARD" from "INBOX" [2016-08-24 三 11:10]
    wait for more.

Capture Time:[2016-03-04 五 16:52]


如果提交之后,想要修改提交日志,可以用 git commit --amend 这样会将提交日志修改,同时提交号会自动相应修改。

5.8 WAIT/FORWARD git如何管理软链接?

  • State "WAIT/FORWARD" from "INBOX" [2016-08-24 三 11:01]
    已经实践确认,需要进一步整理。

Capture Time:[2016-07-28 四 15:56]


实践的结果:

5.8.1 软链接

结论:软链接会在clone中仍然以软链接的方式管理,并且clone中软链接的值和orig中一样,即便不存在。

origin中创建一个相对路径的和绝对路径的软链接,clone之后,相应的文件也是软链接,软链接所指向的路径和origin中的一样。而非根据clone进行相应调整。

miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ cd 10
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ls
1
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ pwd
/home/miracle/test/git/orig_repos/10
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ln -s /home/miracle/test/git/orig_repos/2 .
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ls -l
总用量 0
lrwxrwxrwx 1 miracle video  4  7月 28 16:09 1 -> ../1   
lrwxrwxrwx 1 miracle video 35  7月 28 16:11 2 -> /home/miracle/test/git/orig_repos/2

miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ cd ..
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ git add .
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ git commit -m 'add absolute softlink'
miracle@miracle-Zhaoyang-E49:~/test/git/clone_repos$ git pull
miracle@miracle-Zhaoyang-E49:~/test/git/clone_repos/10$ ls -l
总用量 0
lrwxrwxrwx 1 miracle video  4  7月 28 16:09 1 -> ../1   
lrwxrwxrwx 1 miracle video 35  7月 28 16:11 2 -> /home/miracle/test/git/orig_repos/2

5.8.2 硬链接

结论:硬链接,会做为独立文件在clone中保存,占用额外空间。

origin中创建一个大文件的硬链接,提交上去之后,发现origin的总空间只有一份大文件。

miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ du -shc *
4.0K    1
4.0K    10
4.0K    2
4.0K    3
4.0K    4
4.0K    5
4.0K    6
4.0K    7
8.0K    8
8.0K    9
292K    lxr-2.0.3.tgz
340K    总用量
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ cd 10
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ls
1  2
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ln ../lxr-2.0.3.tgz
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ls
1  2  lxr-2.0.3.tgz
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ ls -l
总用量 292
lrwxrwxrwx 1 miracle video      4  7月 28 16:08 1 -> ../1
lrwxrwxrwx 1 miracle video     35  7月 28 16:10 2 -> /home/miracle/test/git/orig_repos/2
-rw-rw-r-- 2 miracle video 296434  7月 22  2015 lxr-2.0.3.tgz
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos/10$ cd ..
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ du -shc *
4.0K    1
296K    10
4.0K    2
4.0K    3
4.0K    4
4.0K    5
4.0K    6
4.0K    7
8.0K    8
8.0K    9
340K    总用量
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ git add .
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ git commit -m 'add hardlink'
[master 36db099] add hardlink
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 10/lxr-2.0.3.tgz
miracle@miracle-Zhaoyang-E49:~/test/git/orig_repos$ du -shc *
4.0K    1
296K    10
4.0K    2
4.0K    3
4.0K    4
4.0K    5
4.0K    6
4.0K    7
8.0K    8
8.0K    9
340K    总用量

clone进行pull之后,硬链接的相应路径处,是单独拷贝的一个文件,clone的空间反而有两份大文件。

miracle@miracle-Zhaoyang-E49:~/test/git$ cd clone_repos/
miracle@miracle-Zhaoyang-E49:~/test/git/clone_repos$ ls 
1  10  2  3  4  5  6  7  8  9  lxr-2.0.3.tgz
miracle@miracle-Zhaoyang-E49:~/test/git/clone_repos$ git pull
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/miracle/test/git/orig_repos
   1037bba..36db099  master     -> origin/master
Updating 1037bba..36db099
Fast-forward
 10/lxr-2.0.3.tgz |  Bin 0 -> 296434 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 10/lxr-2.0.3.tgz
miracle@miracle-Zhaoyang-E49:~/test/git/clone_repos$ git status .
# On branch master
nothing to commit (working directory clean)
miracle@miracle-Zhaoyang-E49:~/test/git/clone_repos$ du -shc *
4.0K    1
296K    10
4.0K    2
4.0K    3
4.0K    4
4.0K    5
4.0K    6
4.0K    7
8.0K    8
8.0K    9
292K    lxr-2.0.3.tgz
632K    总用量

5.9 LATER git submodule研究

  • State "LATER" from "NEXT" [2016-08-24 三 11:10]
  • State "NEXT" from [2016-08-24 三 11:10]

5.10 LATER git的push和pull如何实现免密码?

  • State "LATER" from "WAIT/FORWARD" [2016-12-15 四 17:24]
  • State "WAIT/FORWARD" from "WAIT/FORWARD" [2016-12-15 四 17:24]
    wait for move
  • State "WAIT/FORWARD" from "INBOX" [2016-12-15 四 17:24]

Capture Time:[2016-09-05 一 10:57]


5.11 LATER git push技巧

  • State "LATER" from "INBOX" [2017-04-07 五 16:17]

Capture Time:[2017-02-21 二 11:10]

  1. 首先将本地修改提交到本地( git add && git commit && git pull --rebase)
  2. 本地编译
  3. 不用管编译的中间文件,如果编译通过,直接用 git push xxx HEAD:refs/for/xxx 提交。

5.12 WAIT/FORWARD .gitignore 中列出的文件在 git add 之后,就不管用了。

  • State "WAIT/FORWARD" from "LATER" [2017-04-07 五 16:27]
    wait for arranged.
  • State "LATER" from "INBOX" [2017-04-07 五 16:27]

Capture Time:[2017-03-31 五 21:07]

5.13 WAIT/FORWARD git dir

  • State "WAIT/FORWARD" from "LATER" [2017-04-07 五 16:30]
    wait for arranged.
  • State "LATER" from "INBOX" [2017-04-07 五 16:30]

Capture Time:[2017-04-06 四 17:33]

如果想要将 '.git/' 目录放到另外一个地方,在工作目录中创建 '.git' 文件指向实际的 '.git/' 目录,如下:

$vim .git
 gitdir: /home/miracle/mydata/cloud/MEGAsync/mydata/study/mygitrepo/vaqeteart.github.io.git

5.14 LATER 理解git原理的关键

  • State "LATER" from [2017-04-08 六 10:50]

5.14.1 分布式的理解

基于 git 的分布式版本控制,每个端都是独立的服务器,通过 git pull / git push 相互同步。

5.14.2 工作流程、状态

主要指 svn & gitadd,commit,status, 各有何不同?

5.14.3 工作空间(work area)、缓存空间(staged area)、库(repository)

最好能有相应配图。

5.14.4 针对 git 的内容

object, snapshot, index, repository.

git directory, git work directory, fast-forward.

5.15 NEXT git checkout 到一个 git log 中非HEAD的版本后,如何checkout回来?

  • State "NEXT" from [2017-04-12 三 13:51]

5.16 NEXT git reflog

  • State "NEXT" from [2017-04-12 三 13:51]

5.17 NEXT git mergebase ref1 ref2

  • State "NEXT" from [2017-04-12 三 14:17]

5.18 NEXT git shortlog

  • State "NEXT" from [2017-04-13 四 10:12]

按照用户名来归类信息。

5.19 分支合并的一个例子

目前在一个FVP分支下进行工作主要修改的目录是 apollo/third_party, 但是主分支上的修改需要有如下两种方式同步:

  1. 要么定期合并到FVP
  2. 要么基于最新主分支新开一个FVP分支, 然后把之前的FVP分支工作合并到新FVP.

目前采用第2中方案.所以每次集成之前,需要先将旧的FVP分支迁移到新的FVP分支上. 过程用实例说明,大致过程如下

5.19.1 先切换到新的分支上

$repo init -u ssh://url/tpv/platform/manifest -b 2k17_mtk_archer_m_devprod_FVP_R2_21
$repo sync

5.19.2 确认修改工作所在路径的新旧分支公共的 commit ID

miracle.lv@cnszs215:~/masf/apollo/third_party$ pwd
/home/miracle.lv/masf/apollo/third_party

miracle.lv@cnszs215:~/masf/apollo/third_party$ git merge-base origin/2k17_mtk_archer_m_devprod_FVP origin/2k17_mtk_archer_m_devprod_FVP_R2_21 |git show
commit 85d9f860bd0c82dfceca081ab9da0fb8a7bbf007
Author: patrick.lee <Patrick.Lee@tpv-tech.com>
Date:   Wed Mar 15 17:39:44 2017 +0800
.....

5.19.3 修改工作目录切换到新FVP分支,并

miracle.lv@cnszs215:~/masf/apollo/third_party$git branch -a |grep FVP
miracle.lv@cnszs215:~/masf/apollo/third_party$git checkout -b 2k17_mtk_archer_m_devprod_FVP_R2_21 origin/2k17_mtk_archer_m_devprod_FVP_R2_21

5.19.4 记录新分支的HEAD

miracle.lv@cnszs215:~/masf/apollo/third_party$git log
commit 85d9f860bd0c82dfceca081ab9da0fb8a7bbf007
Author: patrick.lee <Patrick.Lee@tpv-tech.com>
Date:   Wed Mar 15 17:39:44 2017 +0800

    Merger_t-apollo-mp-1501-1550-5-001-15-001-206-001-243

    Change-Id: I5d8d4af735664f183a2782c7680ad342eb90da97

5.19.5 将旧分支工作合并到新分支

5.19.5.1 尝试直接合并
$git merge --commit origin/2k17_mtk_archer_m_devprod_FVP 2>&1 |tee conflict
5.19.5.2cat conflict 查看冲突信息提示
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/player/libspotify_player.so (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/main.o (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/SpotifyMtk.o (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/Player.o (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/BridgeCallbacks.o (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/spotifyjsplugin.so (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
warning: Cannot merge binary files: source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/include/jspp/main.o (HEAD vs. origin/2k17_mtk_archer_m_devprod_FVP)
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/player/libspotify_player.so
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/player/libspotify_player.so
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/main.o
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/main.o
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/SpotifyMtk.o
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/SpotifyMtk.o
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/Player.o
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/Player.o
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/BridgeCallbacks.o
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/BridgeCallbacks.o
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/spotifyjsplugin.so
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/spotifyjsplugin.so
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/include/jspp/main.o
CONFLICT (content): Merge conflict in source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/include/jspp/main.o
Removing source/browser_engine/v2.0/source/browserstub/opera/sdk40/operasdk/include/opera/events/CanStartHbbTVApplication.h
Auto-merging source/browser_engine/v2.0/source/browserstub/opera/sdk40/backend/include/uva_memory_deprecated.h
Removing source/browser_engine/v2.0/source/browserstub/opera/sdk40/backend/Uvawidevine/wv_api.h
Removing source/browser_engine/v2.0/source/browserstub/opera/sdk40/backend/Uvawidevine/wv_api.cpp
Removing source/browser_engine/v2.0/source/browserstub/opera/sdk40/backend/Uvawidevine/managed_drm_backend.h
Removing source/browser_engine/v2.0/source/browserstub/opera/sdk40/backend/Uvawidevine/managed_drm_backend.cpp
Removing source/browser_engine/v2.0/source/browserstub/opera/sdk40/backend/Uvawidevine/include/wvadapter.h
Automatic merge failed; fix conflicts and then commit the result.
5.19.5.3git status 查看冲突
$git status
...
Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/include/jspp/main.o
        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/spotifyjsplugin.so
        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/BridgeCallbacks.o
        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/Player.o
        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/SpotifyMtk.o
        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/main.o
        both modified:      source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/player/libspotify_player.so
5.19.5.4 解决冲突的一个方式

具体视情况而定,这里冲突文件以二进制冲突做为例子,并且解决方案是只采用旧分支的二进制文件.

$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/include/jspp/main.o --theirs
$git add source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/include/jspp/main.o
$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/spotifyjsplugin.so --theirs
$git source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/spotifyjsplugin.so
$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/BridgeCallbacks.o --theirs
$git add source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/BridgeCallbacks.o
$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/Player.o --theirs
$git add source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/Player.o
$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/SpotifyMtk.o --theirs
$git add source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/SpotifyMtk.o
$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/main.o --theirs
$git add source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/jsplugin/build_out/src/main.o
$git checkout source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/player/libspotify_player.so --theirs
$git add source/browser_engine/v2.0/source/browserstub/opera/sdk40/plugins/spotifyjsplugin/player/libspotify_player.so
5.19.5.5 编辑器
$git config --global core.editor vim

5.20 回退与合并指定区间的例子

目标:主分支(master)在A处,建立了分支(b1), 经过一段时间主分支到达B,b1变成(b1*),这时候建立分支(b2),目的是丢弃主分支A->B的修改,直接将b2变成b1*。

b1            ---------b1*---
             /
Master -----*(A)------*(B)-----
                       \
b2                      -----

过程如下

5.20.1 确认 b1b2 的共通祖先 A

$git merge-base b1 b2

具体参见 man git merge-base

5.20.2b2 回退到 A

$git revert -n A..HEAD
$git commit -m 'roll back to A.'

注意,如果没有 -n, 将会对 A~HEAD 的每次 commit 生成一个 revert commit.

对于出现merge的commit,因为涉及到多个分支的提交,所以会出现错误,需要仔细参考 man 手册,通过 -m 选择revert哪个分支的提交。

或者:

$git diff HEAD A >rollbackA.diff
$git apply rollbackA.diff
$rm rollbackA.diff
$git add .
$git commit -m 'roll back to A.'

但是对二进制却不行。

5.20.3Ab1* 的修改应用到回退完的 b2

$git merge --commit b1

理论上应该没有冲突。

5.21 man gitignore

不能工作的方式:

opera-devices-sdk/*
!opera-devices-sdk/include/opera/
!opera-devices-sdk/src/jsplugins/include/*
!opera-devices-sdk/lib/*
!opera-devices-sdk/3rdpartylibs/gstreamer-plugins/*
!opera-devices-sdk/opera_dir/
!opera-devices-sdk/src/uva/include/*
!opera-devices-sdk/utils/fontconfig*/*
!opera-devices-sdk/utils/nss-3*/*

可以工作的方式:

#Ignore list for opera sdk.
#ignore level0 subfiles and list tracked subfiles
opera-devices-sdk/*
!opera-devices-sdk/lib/
!opera-devices-sdk/opera_dir/
!opera-devices-sdk/3rdpartylibs/
!opera-devices-sdk/include/
!opera-devices-sdk/src/
!opera-devices-sdk/utils/
!opera-devices-sdk/pkg-info.json

#ignore level1 subfiles and list tracked subfiles
opera-devices-sdk/3rdpartylibs/*
!opera-devices-sdk/3rdpartylibs/gstreamer-plugins/

opera-devices-sdk/include/*
!opera-devices-sdk/include/opera/

opera-devices-sdk/utils/*
!opera-devices-sdk/utils/fontconfig*/
!opera-devices-sdk/utils/nss-3*/

opera-devices-sdk/src/*
!opera-devices-sdk/src/jsplugins/
!opera-devices-sdk/src/uva/

#ignore level2 subfiles, and list tracked subfiles
opera-devices-sdk/src/jsplugins/*
!opera-devices-sdk/src/jsplugins/include/

opera-devices-sdk/src/uva/*
!opera-devices-sdk/src/uva/include/

5.22 git checkout 后退后,如何前进?

5.23 REFERENCE git 二分法定位问题

  • State "NEXT" from [2017-11-20 一 16:13]

用于迅速定位到有问题的提交。

5.23.1 过程

  1. 开始定位

    $git bisect start
    
  2. 设置当前状态

    $git bisect bad
    
  3. 设置第一个印象中好的状态

    $git bisect good <commit id>
    
  4. 测试

    设置好 badgood 之后,git 会将你切换到一个临时无名分支,进行二分法测试。这个时候,你可以先清理一下工作目录,然后编译、测试等等。

  5. 设置测试结果

    如果测试结果仍旧为坏则 git bisect bad, 如果测试结果为好,则 git bisect good, 之后 git 会按照二分法切换到下一个待测试的提交。

  6. 重复 4, 5 直至结束。

    结束后,git会提示你提交中哪个是最后一个好的,哪个是最后一个坏的。

  7. git bisect reset

    恢复到原有分支状态。

另外,可以通过 git bisect log 查看当前进行的 git bisect 到了什么地方, 通过 git status 得知我们在二分查找。

5.23.2 例子

假设日志如下:

commit a0b8228542cc0385467de07a427b5acefa69ca40
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Nov 9 15:53:30 2017 +0800

    change 3 again.

commit cf432e81d76a96909d96d5ebb5ca9d16ae5d46b9
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Nov 9 15:48:18 2017 +0800

    add in mytest.

commit 205c50d452ed076c7b51405b01040c57036c556e
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Nov 9 15:38:13 2017 +0800

    change1-2

commit 72576a1ea9e437a451f6419d3f9724215d654cd6
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Nov 9 15:36:27 2017 +0800

    commit tracked file

commit 1ad89234301fc2991fda8d46d5e11928ba523235
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Fri Jul 28 10:01:42 2017 +0800

    haha.hahaha.tar.gz

(bad)commit 36db099e3b8a279ef90e79b03f246e0bb61c755a
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Jul 28 16:46:48 2016 +0800

    add hardlink

commit 1037bba71c3b1bd88a2921981bfcefe9b4f67a16
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Jul 28 16:11:14 2016 +0800

    add absolute softlink and large file

(good)commit 50c65f7db679b170720fb35096f7f6183e01b403
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Jul 28 16:08:30 2016 +0800

    add 10 with soft link.

commit 3f31e3ab1de8425ea35fcc63143d7554af3493e4
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Jul 28 16:07:41 2016 +0800

    add init repos

注意这里的 good 表示印象中好用的提交, bad 表示我们要找的第一个引入 bad 的那个目标提交。当前我们在最上面,状态肯定是 bad.

过程如下:

miracle@xmnb4003210:~/test/git/clone_repos$ git bisect start
miracle@xmnb4003210:~/test/git/clone_repos$ git bisect bad
miracle@xmnb4003210:~/test/git/clone_repos$ git bisect good 50c65f7db679b170720fb35096f7f6183e01b403
Bisecting: 3 revisions left to test after this (roughly 2 steps)
[1ad89234301fc2991fda8d46d5e11928ba523235] haha.hahaha.tar.gz
miracle@xmnb4003210:~/test/git/clone_repos$ git status .
头指针分离于 1ad8923
您在执行从分支 'testremote' 开始的二分查找操作。
  (使用 "git bisect reset" 以回到原有分支)

未跟踪的文件:
  (使用 "git add <文件>..." 以包含要提交的内容)

        0001-change1-2.patch
        0002-add-in-mytest.patch
        0003-change-3-again.patch

提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
miracle@xmnb4003210:~/test/git/clone_repos$ git branch
*(非分支,二分查找开始于 testremote)
  master
  mytest
  testremote
miracle@xmnb4003210:~/test/git/clone_repos$ echo "here we perform test"
here we perform test
miracle@xmnb4003210:~/test/git/clone_repos$ echo "test is bad"
test is bad
miracle@xmnb4003210:~/test/git/clone_repos$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 1 step)
[36db099e3b8a279ef90e79b03f246e0bb61c755a] add hardlink
miracle@xmnb4003210:~/test/git/clone_repos$ echo "here we perform test"
here we perform test
miracle@xmnb4003210:~/test/git/clone_repos$ echo "test is bad"
test is bad
miracle@xmnb4003210:~/test/git/clone_repos$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[1037bba71c3b1bd88a2921981bfcefe9b4f67a16] add absolute softlink and large file
miracle@xmnb4003210:~/test/git/clone_repos$ echo "here we perform test"
here we perform test
miracle@xmnb4003210:~/test/git/clone_repos$ echo "test is good"
test is good
miracle@xmnb4003210:~/test/git/clone_repos$ git bisect good
36db099e3b8a279ef90e79b03f246e0bb61c755a is the first bad commit
commit 36db099e3b8a279ef90e79b03f246e0bb61c755a
Author: Miracle <miracle.lv@tpv-tech.com>
Date:   Thu Jul 28 16:46:48 2016 +0800

    add hardlink

:040000 040000 ff9eb5b2293667abd038c3d9696dc5869df7629e 34f962613f37ba1dda10ebdfc4c441ca786deff8 M      10
miracle@xmnb4003210:~/test/git/clone_repos$ git bisect reset
之前的 HEAD 位置是 1037bba... add absolute softlink and large file
切换到分支 'testremote'

5.24 REFERENCE 使用 git loggit rev-list 根据作者和日期筛选提交

Capture Time:[2018-06-04 一 11:37]

git log 命令可以根据作者、时间等信息过滤提交。但是使用时间范围过滤的时候,需要注意以下:

  1. 时间范围是左闭右开的,如 [2018-01-04, 2018-05-30-18:00).
  2. 使用时间范围过滤的时候,这里的时间指的是 CommitDate 而非 AuthorDate.
  3. 默认 git log 只显示 AuthorDate, 需要查看 CommitDate 的话,使用 git log --pretty=fuller.

另外,也可以通过 git rev-list start..end 的方式来输出 start..end 范围内的提交,支持和 git log 类似的选项(这里的 startend 是commit id)。

5.24.1 举例(由来)

5.24.1.1 完整的历史

例如,假设有下列历史:

$git log
 commit 4763149f715b25fadf9bc4f3984dd774de668845
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Tue May 29 18:16:25 2018 +0800

     [Codereview]Add deinit API,mutex protection and Null pointer judgement ect.

     Change-Id: Ie44b11c07e2728ce69169d0176479392d3322c8e

 commit afc73d14bdebbd1991b6b1ebf3fe654caff1f25c
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Thu Apr 26 17:50:16 2018 +0800

     [VideobroadcastBackend]Improve timer code to avoid crash issue
     URTRUCKER:TF418PHIEUMTK02-2860

     Change-Id: I3879f6e8e4a7ddb841e1e0242824f1b249de5f8f
 ......
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Wed Jan 17 15:31:52 2018 +0800

     [VideoBroadcastBackend]Add nonexistchannel case when setchannel NULL
     URTRACKER:TF418PHIEUMTK02-2708

     Change-Id: I208f6332ee2fbd95cd17bb86e63770e9595ac8d5
     (cherry picked from commit b3435586e179346a91d59580838c22392f4487ce)

 commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Wed Jan 3 19:49:09 2018 +0800

     [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
     URTRACKER: TF418PHIEUMTK02-3010

     Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c
5.24.1.2 过滤后的历史(疑惑)

现在过滤 gracex[2018-01-04, 2018-05-29) 的提交,貌似需要如下:

$git log --author=gracex.wang --since=2018-01-04 --until=2018-05-29
 commit afc73d14bdebbd1991b6b1ebf3fe654caff1f25c
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Thu Apr 26 17:50:16 2018 +0800

     [VideobroadcastBackend]Improve timer code to avoid crash issue
     URTRUCKER:TF418PHIEUMTK02-2860

     Change-Id: I3879f6e8e4a7ddb841e1e0242824f1b249de5f8f
 ......
 commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Wed Jan 3 19:49:09 2018 +0800 

     [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
     URTRACKER: TF418PHIEUMTK02-3010

     Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c
$git log --author=gracex.wang --since=2018-01-04 --until=2018-05-30
 commit afc73d14bdebbd1991b6b1ebf3fe654caff1f25c
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Thu Apr 26 17:50:16 2018 +0800

     [VideobroadcastBackend]Improve timer code to avoid crash issue
     URTRUCKER:TF418PHIEUMTK02-2860

     Change-Id: I3879f6e8e4a7ddb841e1e0242824f1b249de5f8f
 ......
 commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
 Author: gracex.wang <gracex.wang@tpv-tech.com>
 Date:   Wed Jan 3 19:49:09 2018 +0800 

     [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
     URTRACKER: TF418PHIEUMTK02-3010

     Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c

可是,过滤的结果却让人产生了困惑,问题是:

  1. 在第一条中,明明指定 --since=2018-01-04, 怎么过滤出了 2018-01-03 的日志?
  2. 在第二条想包含 2018-05-29, 所有指定 --until=2018-05-30=, 可是为什么还是没有输出 =2018-05-29 的日志?
5.24.1.3 包含提交时间的完整历史

前面的异常说明,不是 git log 的时间有问题,就是 git log 过滤的结果有误。

显然后面的情况,不大可能。换一个方式,加上 --pretty=fuller 选项:

$git log --author=gracex --pretty=fuller
commit 4763149f715b25fadf9bc4f3984dd774de668845
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Tue May 29 18:16:25 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Wed May 30 17:59:09 2018 +0800

    [Codereview]Add deinit API,mutex protection and Null pointer judgement ect.

    Change-Id: Ie44b11c07e2728ce69169d0176479392d3322c8e

commit afc73d14bdebbd1991b6b1ebf3fe654caff1f25c
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Thu Apr 26 17:50:16 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Tue May 8 17:44:04 2018 +0800

    [VideobroadcastBackend]Improve timer code to avoid crash issue
    URTRUCKER:TF418PHIEUMTK02-2860

    Change-Id: I3879f6e8e4a7ddb841e1e0242824f1b249de5f8f

......

commit 8eae9515df3f57e2989e2ba9b609881cb678c728
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Wed Jan 17 15:31:52 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Thu Jan 25 18:26:50 2018 +0800

    [VideoBroadcastBackend]Add nonexistchannel case when setchannel NULL
    URTRACKER:TF418PHIEUMTK02-2708

    Change-Id: I208f6332ee2fbd95cd17bb86e63770e9595ac8d5
    (cherry picked from commit b3435586e179346a91d59580838c22392f4487ce)

commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Wed Jan 3 19:49:09 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Thu Jan 4 17:29:52 2018 +0800

    [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
    URTRACKER: TF418PHIEUMTK02-3010

    Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c

发现,原来,除了 AuthorDate 之外,还有一个 CommitDate

5.24.1.4 过滤后包含提交时间的历史(解决疑惑)

那么如下过滤:

$git log --author=gracex.wang --since=2018-01-04 --until=2018-05-29 --pretty=fuller
commit afc73d14bdebbd1991b6b1ebf3fe654caff1f25c
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Thu Apr 26 17:50:16 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Tue May 8 17:44:04 2018 +0800

    [VideobroadcastBackend]Improve timer code to avoid crash issue
    URTRUCKER:TF418PHIEUMTK02-2860

    Change-Id: I3879f6e8e4a7ddb841e1e0242824f1b249de5f8f

......

commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Wed Jan 3 19:49:09 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Thu Jan 4 17:29:52 2018 +0800

    [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
    URTRACKER: TF418PHIEUMTK02-3010

    Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c

$git log --author=gracex.wang --since=2018-01-04 --until=2018-05-30 --pretty=fuller
commit afc73d14bdebbd1991b6b1ebf3fe654caff1f25c
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Thu Apr 26 17:50:16 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Tue May 8 17:44:04 2018 +0800

    [VideobroadcastBackend]Improve timer code to avoid crash issue
    URTRUCKER:TF418PHIEUMTK02-2860

    Change-Id: I3879f6e8e4a7ddb841e1e0242824f1b249de5f8f

......

commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Wed Jan 3 19:49:09 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Thu Jan 4 17:29:52 2018 +0800

    [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
    URTRACKER: TF418PHIEUMTK02-3010

    Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c

$git log --author=gracex.wang --since=2018-01-04 --until=2018-05-30-18:00 --pretty=fuller
commit 4763149f715b25fadf9bc4f3984dd774de668845
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Tue May 29 18:16:25 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Wed May 30 17:59:09 2018 +0800

    [Codereview]Add deinit API,mutex protection and Null pointer judgement ect.

    Change-Id: Ie44b11c07e2728ce69169d0176479392d3322c8e

......

commit bba05e9cd30ec681fe8d6e45afb42c1abd9c1a27
Author:     gracex.wang <gracex.wang@tpv-tech.com>
AuthorDate: Wed Jan 3 19:49:09 2018 +0800
Commit:     Gerrit Code Review <tpv-review@TWCLS071.tpvaoc.com>
CommitDate: Thu Jan 4 17:29:52 2018 +0800

    [BroadcastBackend]Add ProgrammesChangedEvent in videobroadcast backend according to Opera
    URTRACKER: TF418PHIEUMTK02-3010

    Change-Id: I1d4e21bad71d1de90fd56a38c96f01bb96bf390c

这就解释了前面的疑惑: 第一条命令,说明过滤的时候,所依据的时间是 CommitDate 而非 AuthorDate.

第二条命令,说明时间范围是左闭右开的,如 [2018-01-04, 2018-05-30)

第三条命令,说明可以在日期后添加更精确的时间,并且通过比右开区间大的时间,达到选择闭合区间的目的,即:=[2018-01-04 四]=

5.24.1.5 更强大的 git rev-list

CommitDate 是在学习 git rev-list 时发现的, 进而解决了 git log 过滤的疑惑。

git rev-list 命令可以列出指定的提交,选项类似 git log

列出 CommitDate 在时间 [date1, date2) 之间的提交,可以这样:

$git log --author=xxx --since=<date1> --until=<date2>
$git rev-list --author=xxx ==since=<date1> --until=<date2> HEAD

两者不同在于, git rev-list 需要额外给出想要列出的提交起始信息,并且只输出 commit id ;而 git log 会给出额外的信息。

两者都支持 --pretty 选项调整格式, --pretty=fuller 可以显示出包括 CommitDate 在内的更多信息。

举例:

$git log --author=fly --since="Fri Jan 19 15:52:22 2018" --until="Tue May 29 11:42:47 2018"
or
$git log --author=fly --since="2018-01-19-15:52" --until="2018-05-29-11:42"
$git rev-list HEAD --author="damon.zhong\|eric.tang\|fly.zhang\|gracex.wang\|ian.chen\|jerome.wang\|miracle.lv\|paul.deng\|rance.li\|vincent.hong" --since=2018-01-01 --pretty=fuller

5.25 gerrit操作汇集

5.25.1 local

5.25.1.1 正常流程
$git add . #添加修改
$git commit -m 'xxx' #提交到本地
$git push origin HEAD:refs/for/<branch name> #推送到远端

提交之时,会自动在 commit 的comment上追加一个change id(通过hooks实现), 之后,会在 gerrit的My Changes看到。

可以添加reviewer,这样reviewer会收到邮件,让多人参与代码审核。

5.25.1.2 在已有的change id上修改
$git add .
$git commit --amend
$git push origin HEAD:refs/for/<branch name>

如果追加到同样的 change id, 用此方法。

5.25.1.3 临时草稿
$git push origin HEAD:refs/drafts/<branch name>

这个方法,可以添加到gerrit的My Drafts中,用于临时修改, 最终 Publish后会进入到 My Changes中。

5.25.1.4 提前添加reviewer
$git push origin HEAD:refs/drafts/2K18_UI_FFC_tpv%r=jerome.wang@tpv-tech.com,r=lam.lin@tpv-tech.com,r=kiko.han@tpv-tech.com,r=eric.tang@tpv-tech.com,r=gracex.wang@tpv-tech.com,r=paul.deng@tpv-tech.com

这样,可以在提交的时候添加reviewer,而不用在gerrit添加了。

5.25.1.5 查看当前代码所在的git目录路径
$git rev-parse --git-dir
5.25.1.6 拷贝远端hook

比如添加脚本使得commit时会产生gerrit的change id便于push。

$scp -p -P <port> <user>@<ip>:hooks/commit-msg .git/hooks

5.25.2 remote

change id不是commit id, commit id和 change id可以直接在gerrit上搜索定位。

5.26 找到丢失的历史

参考: https://blog.csdn.net/yasin_lee/article/details/51145614

比如:执行checkout -f 或 reset -hard 或 branch -d删除一个分支
结果造成本地(远程)的分支或某些commit丢失
可以通过reflog来进行恢复,前提是丢失的分支或commit信息没有被git gc清除
一般情况下,gc对那些无用的object会保留很长时间后才清除的
reflog是git提供的一个内部工具,用于记录对git仓库进行的各种操作
可以使用git reflog show或git log -g命令来看到所有的操作日志