Как найти индивидуальные переломные изменения в большом коммите - PullRequest
2 голосов
/ 25 января 2012

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

Я мог бы:

  1. diff рабочий (более ранний) коммит против взломанного (более позднего) коммита
  2. сохранить результат в файле патча
  3. патч / тестовый цикл
    1. применить части файла патча к более ранней фиксации
    2. запустить тесты

Я надеюсь, что у git есть что-то менее ручное, чем это.

Ответы [ 3 ]

4 голосов
/ 25 января 2012

Есть неплохой способ сделать это, используя способность git-stash не только скрывать и повторно применять изменения, но также и состояние индекса. Это выглядит примерно так:

# check out the bad commit
git checkout bad-commit
# and then reset to the commit before, leaving the bad changes in the work tree
git reset HEAD^

# stage the things you want to keep/test first
git add -p
# stash away the rest (keep the staged parts)
git stash --keep-index
# now build/test. if it works, go ahead and commit it
git commit
# bring back the stashed changes
git stash pop
# repeat!
git add -p
git stash --keep-index
# now suppose the broken part is in what you kept, and you want to split it up more
# unstage the changes
git reset
# and then repeat!
git add -p
git stash --keep-index
# if you do this, you'll end up with multiple stashes; you can check on them:
git stash list
git stash show
git stash show -p stash@{1}

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

Вы могли бы сделать что-то похожее, чтобы разделить коммит на множество, а затем запустить на нем git bisect, но часто это более трудоемко, поскольку по ходу дела сложнее узнать, как разбить вещи без тестирования. *

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

1 голос
/ 26 января 2012

Я закончил тем, что сделал, по существу, то, что предложил Джефроми. Я написал этот код на Python, назвав его git-bisect.py:

#!/usr/bin/env python

from subprocess import Popen, PIPE
from sys import stderr


def run_command(cmd):
    p = Popen(cmd, stdout=PIPE, stderr=PIPE)
    output, errors = p.communicate()
    if p.returncode:
        raise Exception(errors)


def process_all(filename):
    with open(filename) as f:
        all_files = [fn.strip() for fn in f]
    try:
        for i, f in enumerate(all_files, start=1):
            print >> stderr, i, f
            run_command(['git', 'add', f])
            run_command(['git', 'stash', '--keep-index'])
            run_command(['bin/login_test.sh'])
            run_command(['git', 'stash', 'pop'])
    except Exception, exc:
        print >> stderr, exc


if __name__ == '__main__':
    from sys import argv
    for filename in argv[1:]:
        process_all(filename)

И запустил его по списку файлов, которые были затронуты.

Вот мой полный рабочий процесс:

# Get the commit just before things went bad
git checkout 8f5c3d7
# Diff good code against bad, make patch
git diff 8f5c3d7 cb8ddf0 > 8f5c3d7-cb8ddf0.patch
# Apply patch
git apply 8f5c3d7-cb8ddf0.patch

# Now my index has all the changes that went into the bad commit
# but with just a dirty index.

# Run code that finds bad file in commit
python ~/Dropbox/src/git-bisect.py ~/Dropbox/src/bad-commit.txt

И это продолжалось до тех пор, пока не остановилось на первом плохом файле. Тогда я бы просто:

git reset --hard HEAD

и повторно примените патч, поместите неверный файл в конец списка файлов и начните сначала. Вскоре я узнал файл, в котором были изменения, которые сломали мою сборку.

1 голос
/ 25 января 2012

Вы можете разделить ваш коммит на несколько маленьких, а затем использовать git bisect, чтобы найти оскорбительный коммит.Самый простой способ для этого - использовать интерактивное перебазирование :

  1. Если вы уже нажали коммит, то создайте новую ветку с git checkout -b <name>, в противном случае вы готовы идти.
  2. Выполнить git rebase -i <bad commit>^
  3. Откроется редактор с одной или несколькими строками, каждая из которых указывает на фиксацию.В строке оскорбительного коммита измените первое слово с pick на edit, затем сохраните и закройте редактор.
  4. Git теперь остановится в середине перебазирования, когда все измененияваш оскорбительный акт инсценирован.Теперь мы разделяем этот большой коммит на более мелкие, выполняя git reset для измененных файлов, а затем фиксируя каждое изменение самостоятельно.
  5. Когда вы закончите, выполните git rebase --continue, чтобы завершить процедуру ребазирования..

Теперь вы разделили свой коммит на несколько меньших, и вам легче будет узнать, какие именно изменения нарушены.Очень эффективный способ сделать это - использовать git bisect.Для этого нужно выполнить бинарный поиск коммитов, чтобы найти именно тот, который сломан, и это именно то, чего вы хотите достичь.Вот как вы его используете:

  1. Выполнить git bisect start.
  2. Выполнить git bisect good <good commit>, где <good commit> - хеш / тег / любой коммит, который вы знаете, сработал.Вы можете использовать коммит до того, как только что будет сделан первый из сделанных вами сплит-коммитов.
  3. Выполнить git bisect bad <bad commit>, где <bad commit> - это has / tag / независимо от того, какой коммит вы знаете не работа.Вы можете использовать HEAD для этого, так как вы знаете, что он сломан.
  4. Git теперь извлечет какой-то коммит в этом диапазоне и попросит вас проверить его.Выполните тест, а затем скажите git, хорошо это или плохо, запустив git bisect good или git bisect bad соответственно.Git будет продолжать проверять другие коммиты, в соответствии с тем, что вы им сообщаете.
  5. После некоторых шагов git точно скажет вам, какой коммит нарушен.Затем вы можете использовать git show <commit>, чтобы увидеть, что в нем содержится.
  6. Запустить git bisect reset, чтобы выйти из режима деления пополам.

Чтобы узнать больше об этом предмете, продолжайте читать по:

  1. Git Book о git bisect и интерактивная перебазировка .
  2. Pro Git book о git bisect и интерактивная перебазировка .
  3. man-страницы git (которые, кстати, превосходны!), с git rebase --help и git bisect --help.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...