упрощение истории журнала git - PullRequest
14 голосов
/ 19 июля 2011

Допустим, у меня есть следующая история

        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 --first-parent 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

Yay!

Ответы [ 2 ]

5 голосов
/ 19 июля 2011

Я не думаю, что это возможно напрямую (если вы заранее не знаете точный список для включения / исключения, что сводит на нет цель обхода DAG)

На самом деле, ОП Кену Хиракаве удалось получить ожидаемую линейную историю по:

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

И для каждого коммита убедитесь, что он является прямым потомком предыдущего коммита.

Вот сценарий , написанный Кеном Хиракавой .


Вот мой скрипт для создания группы доступности базы данных, упомянутой в разделе Упрощение истории на странице справки git log, для --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, в том смысле, что «того, что есть у M, не было в D».
Результатом в этом примере будут все коммиты, кроме A и B (и, конечно, D).

Когда мы хотим выяснить, какие коммиты в M загрязнены ошибкой, введенной D, и нуждаются в исправлении , тем не менее, мы можем захотеть просмотреть только подмножество D..M, которое на самом деле являются потомками D, т.е. исключая C и K.
Это именно то, что делает опция --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 голосов
/ 16 апреля 2019

Мне тоже не нравятся проблемы, которые возникают в результате слияния, и я обошелся без них в моей основной истории. Всякий раз, когда происходит слияние с основной ветвью, я повторяю его с идентичным содержимым, но в виде одного коммита.

    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.

...