git日志历史简化

Ken*_*awa 14 git logging history

假设我有以下历史

        D---E-------F
       /     \       \
      B---C---G---H---I---J
     /                     \
    A-------K---------------L--M
Run Code Online (Sandbox Code Playgroud)

git log --ancestry-path D..M会给我

            E-------F
             \       \
              G---H---I---J
                           \
                            L--M
Run Code Online (Sandbox Code Playgroud)

但是,我想要以下几点

            E
             \       
              G---H---I---J
                           \
                            L--M
Run Code Online (Sandbox Code Playgroud)

要么

            E-------F
                     \
                      I---J
                           \
                            L--M
Run Code Online (Sandbox Code Playgroud)

从本质上讲,我只想走一条路,而不是两条路.

这可能吗?如果是这样,命令是什么?

编辑:

我尝试过使用--first-parent,但事实并非如此.git log - 第一父母G..M给了我

                    F
                     \
                  H---I---J
                           \
                            L--M
Run Code Online (Sandbox Code Playgroud)

它包括F,因为F是I的第一个父母.相反,我喜欢

                  H---I---J
                           \
                            L--M
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激

解决方案(对我有用):

正如@VonC所说的那样,没有一个单线程可以做到这一点.所以我最终使用了一个bash脚本.

  1. 对于'git log --ancestry-path G..M'中的每个提交
  2. 确定$ commit的父级是否包含我们之前的提交
  3. 如果是,请继续.做一些有趣的事.
  4. 如果不是,请跳过该提交.

例如,git log --first-commit G..M是

H - F - I - J - L - M
Run Code Online (Sandbox Code Playgroud)

然而,F的父母是E,而不是H.所以我们省略F,给我

H - I - J - L - M
Run Code Online (Sandbox Code Playgroud)

好极了!

Von*_*onC 5

我认为这是不可能直接实现的(除非您事先知道要包含/排除的确切列表,否则将忽略执行DAG的目的)

实际上,OP Ken Hirakawa通过以下方法设法获得了预期的线性历史记录:

git log --pretty=format:"%h%n" --ancestry-path --reverse $prev_commit..$end_commit
Run Code Online (Sandbox Code Playgroud)

对于每次提交,请确保它是上一次提交的直接子代。

这是平川健写剧本


这是我的脚本,用于创建git log手册页的“ 历史记录简化”部分中提到的DAG ,用于--ancestry-path

最后,您会发现我用来创建类似历史记录的bash脚本(使用根目录的名称和您的用户名来调用它)。

我定义:

$ git config --global alias.lgg "log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative"
Run Code Online (Sandbox Code Playgroud)

我得到:

$ git lgg
* d7c4459 - (HEAD, M, fromA) M <VonC>
*   82b011d - (L) Merge commit 'J' into fromA <VonC>
|\
| * 190265b - (J, master) J <VonC>
| *   ef8e325 - (I) Merge commit 'F' <VonC>
| |\
| | * 4b6d976 - (F, fromB) F <VonC>
| * | 45a5d4d - (H) H <VonC>
| * |   834b239 - (G) Merge commit 'E' <VonC>
| |\ \
| | |/
| | * f8e9272 - (E) E <VonC>
| | * 96b5538 - (D) D <VonC>
| * | 49eff7f - (C) C <VonC>
| |/
| * 02c3ef4 - (B) B <VonC>
* | c0d9e1e - (K) K <VonC>
|/
* 6530d79 - (A) A <VonC>
Run Code Online (Sandbox Code Playgroud)

从那里,我不能排除提交I的父母之一。

祖先路径确实返回:

$ git lgg --ancestry-path D..M
* d7c4459 - (HEAD, M, fromA) M <VonC>
* 82b011d - (L) Merge commit 'J' into fromA <VonC>
* 190265b - (J, master) J <VonC>
*   ef8e325 - (I) Merge commit 'F' <VonC>
|\
| * 4b6d976 - (F, fromB) F <VonC>
* | 45a5d4d - (H) H <VonC>
* | 834b239 - (G) Merge commit 'E' <VonC>
|/
* f8e9272 - (E) E <VonC>
Run Code Online (Sandbox Code Playgroud)

与日志手册页一致:

常规D..M计算属于祖先的提交集M,但不包括作为祖先的提交集D
这对于了解M自那时以来发生的历史很有用D,在某种意义上说“确实M有什么不存在D”。
此示例中的结果是除ABD当然还有其本身)之外的所有提交。

但是,当我们想找出哪些提交M被bug所污染D并需要修复时,我们可能只想查看D..M实际上属于的子集D,即排除CK
这正是该--ancestry-path选项的作用。


#!/bin/bash

function makeCommit() {
  local letter=$1
  if [[ `git tag -l $letter` == "" ]] ; then
    echo $letter > $root/$letter
    git add .
    git commit -m "${letter}"
    git tag -m "${letter}" $letter
  else
    echo "commit $letter already there"
  fi
}

function makeMerge() {
  local letter=$1
  local from=$2
  if [[ `git tag -l $letter` == "" ]] ; then
    git merge $from
    git tag -m "${letter}" $letter
  else
    echo "merge $letter already done"
  fi
}

function makeBranch() {
  local branch=$1
  local from=$2
  if [[ "$(git branch|grep $1)" == "" ]] ; then
    git checkout -b $branch $from
  else
    echo "branch $branch already created"
    git checkout $branch
  fi
}

root=$1
user=$2
if [[ ! -e $root/.git ]] ; then
  git init $root
fi
export GIT_WORK_TREE="./$root"
export GIT_DIR="./$root/.git"
git config --local user.name $2

makeCommit "A"
makeCommit "B"
makeCommit "C"
makeBranch "fromB" "B"
makeCommit "D"
makeCommit "E"
makeCommit "F"
git checkout master
makeMerge "G" "E"
makeCommit "H"
makeMerge "I" "F"
makeCommit "J"
makeBranch "fromA" "A"
makeCommit "K"
makeMerge "L" "J"
makeCommit "M"
Run Code Online (Sandbox Code Playgroud)