Git: вернуться к отметке времени и запустить тест с каждым коммитом?

Есть 5 коммитов, которые содержат новую экспериментальную функцию, но она делает мастер слишком медленным, причина до сих пор неизвестна. Как я могу спрятать новые коммиты или создать для них ветку, например ExpA, чтобы они не испортили основную ветку?

Идея отдельного каталога

Происходит из

...--o--o--A--B--C--D--E   <-- master

следующие репозитории для разделения каталогов A, B, C, D и E в указанном порядке:

...--o--o--A   <-- master

...--o--o--A--B   <-- master

...--o--o--A--B--C   <-- master

...--o--o--A--B--C--D   <-- master

...--o--o--A--B--C--D--E   <-- master

но также можно переформулировать цель с точки зрения ветвей, поэтому вместо создания отдельных каталогов создайте новые ветки A, B, C, D и E, чтобы было легко запустить файл tester.m, просто изменив ветвь.

Идея создания отдельного филиала

     ---- A   <-- A
     |
     |------ A--B   <-- B
     ||
     || --- A--B--C   <-- C
     || |
     || |  A--B--C--D   <-- D
     \\ | /
      \\|/
...--o--o   
         \
          A--B--C--D--E   <-- master

Как проверить каждую фиксацию и почему? С некоторыми из вышеперечисленных идей?

Предлагайте и другие идеи, если они у вас есть! Может быть какая-то программа с графическим интерфейсом, в которой курсор над фиксацией и нажатие какой-либо клавиши запускает сцену — такая функция, кстати, была бы очень крутой в Tig.


person hhh    schedule 24.01.2014    source источник
comment
Без создания новых веток или репозиториев: просто выполните git checkout A и запустите тест; затем выполните git checkout B и запустите свой тест и т. д. — Вы можете проверить любой коммит в отдельном HEAD, чтобы запустить свои тесты на версии этого коммита.   -  person poke    schedule 24.01.2014
comment
Похоже, вам действительно нужно здесь git bisect master A~.   -  person Greg Bacon    schedule 24.01.2014
comment
@GregBacon, что такое A~? Это хэш коммита? Например, git bisect 6f99fb970ddfcac4cd0bd8385b4f788f214e1df9~ ... пока не могу понять git bisect: /how-to-use-git-bisect. Это для меня, если я не хочу избавляться от коммитов? Я хотел бы сделать A-B-C-D-E экспериментальной функцией. Мне нужно сначала найти точку A, которая может быть сложной частью, разделить ее пополам?   -  person hhh    schedule 25.01.2014
comment
@hhh Да, такое использование SHA будет работать. Это означает родителя A, последний известный хороший коммит. Разделение пополам точно определяет фиксацию, вызвавшую проблему, используя наименьшее количество тестов, O(log n).   -  person Greg Bacon    schedule 25.01.2014
comment
@GregBacon слушайте, я хотел бы сделать это: git bisect bad (перейти на один коммит назад), git bisect bad 3 (перейти на 3 коммита назад), а затем я нашел хороший коммит - это следующий главный старт, куда я хочу двигаться плохие совершают ветку экспериментальной функции. Прежде чем поставить отметку «плохо», мне нужно выполнить быстрый тест с файлом ./tester.m, чтобы проверить, работает ли что-то вручную. Вольф объясняет выполнение ветки, stackoverflow.com/a/21334690/164148, но теперь мне просто нужно найти правильную точку . Как сделать этот процесс?   -  person hhh    schedule 25.01.2014


Ответы (3)


Допустим, ваша ветка master выглядит так:

    --A--B--C--D--E--F--G (master)

C, D, E, F и G — это коммиты, которые вам больше не нужны на master. Таким образом, ваша цель состоит в том, чтобы сделать их ветвью и сбросить мастер до B. Поэтому

(0) git checkout master

(1) git branch experimental G

(2) git reset --hard B

Это оставит вас с:

    --A--B (master)
          \
           C--D--E--F--G (experimental)

Теперь вы можете собрать master без экспериментальных коммитов; а на экспериментальной ветке можно все построить.

person Wolf    schedule 24.01.2014
comment
Не проверял это, но я думаю, что это решает одну проблему: перемещение экспериментальных коммитов в новую ветку, +1 за нее. Теперь мне нужно найти, как найти этот плохой коммит, по-видимому, с git bisect. - person hhh; 25.01.2014

Возможно, источник Git-канал Freenode.

git checkout -b <newbranchname> 'master@{2014-01-11 22:35}'
person hhh    schedule 24.01.2014

Здесь вам нужно знать, что «структурная ветвь» (сейчас я экспериментирую с этим термином) формируется графом фиксации, а метка git-ветви просто «вставляется» в фиксацию. (или «указывает» на один коммит, если вы предпочитаете эту терминологию).

Похоже, у вас сейчас есть что-то вроде этого:

...--o--o--A--B--C--D--E   <-- master

где с A по E — пять коммитов, которые представляют собой эту новую экспериментальную функцию, а более ранние o — другие коммиты. (Обратите внимание, что «время движется вперед» слева направо, т. е. последняя фиксация o произошла до A, а A — до B и так далее.)

Нарисуем вышеизложенное с изломом на линии, который ее никак не меняет, но освобождает место на рисунке для того, чтобы наклеить на нее вторую метку. Затем наклеим на него вторую этикетку.

...--o--o   <-- new-label
         \
          A--B--C--D--E   <-- master

Посмотрите, как, если бы мы могли просто поменять местами эти две метки, мы бы получили именно то, что вы просили: master указывало бы на последнюю фиксацию непосредственно перед A, а new-label указывало бы на фиксацию E, которая затем "ответвлялась бы от master".

Мы можем сделать именно это. Есть только одно предостережение: если кто-то еще использует этот репозиторий, либо напрямую, либо (чаще) с помощью операций push и pull, другие люди ожидают только, что метки веток будут "двигаться вперед": иметь новые коммиты добавляются с течением времени, а не коммиты, которые "забираются" из-за возвращения "в прошлое".

Если они подобрали ваши новые коммиты (с A по E) и действие "переместить метку ветки master вперед" с последнего коммита o на E, а затем вы решили "переместить метка задом наперед", вы должны как-то сказать им: "Эй, ребята, извините, но я должен был вовремя переместить метку назад". Затем им, возможно, придется предпринять дополнительные действия самостоятельно, чтобы оправиться от этого.

Если ни у кого еще нет коммитов, вы в отличной форме. Если у кого-то они могут быть, но они ими не пользуются, или они согласны предпринимать действия, чтобы оправиться от «движения назад», то вы все еще в хорошей форме.

Вот один из кратчайших способов добиться трюка с метками (есть еще несколько не менее коротких способов):

  1. Добавьте новую метку, указывающую на коммит E:

    git checkout master  # if you're not already "on branch master"
    git checkout -b ExpA
    

    (преимущество этого метода заключается в том, что он оставляет вас «на ветке ExpA», что, как я полагаю, вам бы хотелось).

  2. Теперь, когда у E есть вторая метка, принудительно переместите master назад на пять коммитов:

    git branch -f master master~5
    

    (master~5 означает «переместиться на 5 коммитов назад от того места, где сейчас находится master; вы можете использовать любой другой метод, чтобы назвать желаемый коммит, который является последним узлом o на рисунках выше; master@{date}, как в вашем собственном ответе, может помочь, например ).

  3. Только если вы уже pushed совершаете коммиты с A по E в какой-то центральный репозиторий (здесь, я полагаю, он называется origin) в ветке master. Обратите внимание, что этот шаг, по крайней мере, немного опасен (иногда более чем слегка, если другие запихнули туда больше коммитов на master) и не должен выполняться до тех пор, пока все остальные не узнают об этом и не согласятся с этим (и если вы не знаете то, что вы здесь делаете, пусть вместо этого это сделает кто-то другой — тот, кто отвечает за центральное хранилище origin):

    git push -f origin master
    

Если у других есть ваши коммиты, а вам не разрешено "вернуться в прошлое" с помощью меток, вам нужно вместо этого "откатить" материал; см. другие обсуждения StackOverflow по этому поводу.

person torek    schedule 24.01.2014
comment
Является ли label термином git? Извините, я как-то ввел в заблуждение начало, такое как structural branch. Во-первых, мне нужно узнать начало 'real master'. Затем мне нужно переместить все коммиты до этого в экспериментальную ветку. Возможно, второй пункт git bracnh -f master master~5 делает это? Перемещает ли он пять первых коммитов в новую ветку принудительно? Но как называется экспериментальная ветка? - person hhh; 25.01.2014
comment
Метка – это обычное англоязычное слово, которое я использую в значении существительного. Это касается имен веток git, имен тегов git и специальных ссылок, таких как stash (используется git stash). В большей части поста я использую его более конкретно для ссылки на имя ветки git, не путать со структурой данных, сформированной путем следования родительским идентификаторам коммитов в серии коммитов, которые git также вызывает ветвь. Я боюсь, что у нас могут быть некоторые проблемы с языковым барьером, помимо собственной проблемы git с использованием одного слова (ветвь) для двух разных идей. - person torek; 25.01.2014