Подтвердить что ты не робот

Git облегчение истории журналов

Скажем, у меня есть следующая история

        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

По сути, я хотел бы пройти только один путь, а не два.

Возможно ли это? И если да, то какая команда?

Edit:

Я пробовал использовать - first-parent, но это не совсем так. git log -first-parent G..M дает мне

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

Он включает F, потому что F является первым родителем I. Вместо этого я хотел бы

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

Любая помощь будет оценена

Решение (это сработало для меня):

Как заявила @VonC, для этого нет ни одного однострочного вкладыша. Поэтому я закончил использование bash script.

  • Для каждой фиксации в 'git log -ancestry-path G..M'
  • Определите, включен ли родитель $commit, который мы ранее делали в
  • Если да, продолжайте. сделать что-то интересное.
  • Если нет, пропустите эту фиксацию.

Например, git log -first-commit G..M

H - F - I - J - L - M

Однако родитель F - это E, а не H. Поэтому мы опускаем F, давая мне

H - I - J - L - M

Yay!

4b9b3361

Ответ 1

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

На самом деле OP Ken Hirakawa удалось получить ожидаемую линейную историю:

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

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

Вот script, написанный Ken Hirakawa.


Вот мой script, чтобы создать DAG, упомянутую в разделе "Упрощение истории" страницы журнала журнала git, для --ancestry-path:

В конце вы найдете bash script, который я использовал для создания подобной истории (назовите ее именем корневого каталога и вашим именем пользователя).

Я определяю:

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

Возвращает путь ancestry:

$ 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 и BD, конечно).

Когда мы хотим узнать, что зафиксировано в 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"

Ответ 2

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

    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.