git日志历史简化

问题描述 投票:14回答:2

假设我有以下历史

        D---E-------F
       /     \       \
      B---C---G---H---I---J
     /                     \
    A-------K---------------L--M

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

            E-------F
             \       \
              G---H---I---J
                           \
                            L--M

但是,我想要以下几点

            E
             \       
              G---H---I---J
                           \
                            L--M

要么

            E-------F
                     \
                      I---J
                           \
                            L--M

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

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

编辑:

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

                    F
                     \
                  H---I---J
                           \
                            L--M

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

                  H---I---J
                           \
                            L--M

任何帮助,将不胜感激

解决方案(对我有用):

正如@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

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

H - I - J - L - M

耶!

git history logging
2个回答
5
投票

我不认为这是直接可能的(除非您事先知道包含/排除的确切列表,这否定了行走DAG的目的)

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

git log --pretty=format:"%h%n" --ancestry-path --reverse $prev_commit..$end_commit

并且对于每次提交,确保它是前一次提交的直接子项。

这是script writtten by Ken Hirakawa


这是我的脚本,用于创建git日志手册页的History Simplification部分中提到的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"

我明白了:

$ 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>

从那里,我不能排除承诺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>

这与日志手册页一致:

常规D..M计算M祖先的一组提交,但不包括那些D的祖先。 这有助于了解自M以来导致D的历史发生了什么,其意义是“MD中不存在什么”。 这个例子中的结果将是所有提交,除了AB(当然还有D本身)。

当我们想要了解M中的哪些提交被D引入的bug所污染并且需要修复时,我们可能只想查看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"

0
投票

我也不喜欢合并带来的问题,并且在我的主流历史中已经放弃了它。每当在主分支上有大的合并时,我将重新发送它具有相同的内容但作为单个提交。

    D---E--------F                           Co-Developer
   /               
  B---C---G'---H---I'--J                     Team Leader
 /                       
A-------K----------------L'--M               Main Stream

在这里,G',I'和L'将是我重新提交合并结果的点。分支描述简单地描述了我可以可视化问题树发生的场景。因此,G和G'的内容(类似于我和我)将是相同的,团队领导者已经合并了开发人员的工作。 L'与L相同,功能集成到主流。

I totally understand that avoiding a problem is not the same as solving it, and sympathize with those facing the problem now.

© www.soinside.com 2019 - 2024. All rights reserved.