2013-06-24 2 views
32

У меня есть история, которая выглядит следующим образом:Git разрез`ать с объединенными фиксаций

* 3830e61 Add data escaping.    (Bad) 
* 0f5e148 Improve function for getting page template. 
* aaf8dc5 Merge branch 'navigation' 
|\ 
| * 3e667f8 Add icons. 
| * 43a07b1 Add menu styles.    (Breaks) 
| * 107ca95 Add Responsive Nav.   (Good) 
* | ea3d736 Add ‘Admin’ notice. 
* | 17ca0bb Update placeholder text. 
|/ 
* f52cc34 Add featured image. 
* 2abd954 Style placeholders. 

Я пытаюсь узнать больше и git bisect, но у меня возникают проблемы с этой историей. Я знаю, что 107ca95 хорош и 3830e61 - это плохо. Когда я запускаю git bisect, коммиты 107ca95..3e667f8 игнорируются. Я знаю, что 43a07b1 - это фиксация, введя регрессию, но она никогда не оценивается.

Вот примерно то, что я сделал:

git checkout master 
git bisect start 
git bisect bad 
git bisect good 107ca95 
git bisect bad (multiple times) 

Независимо от того, что я делаю, 107ca95..3e667f8 никогда не проверяются, чтобы проверить.

Есть ли способ, по которому я могу по существу «сгладить» историю во время биссекта, чтобы проверить эти коммиты? Я знаю, что могу использовать интерактивный rebase, чтобы сгладить историю, но я не хочу этого делать.

+0

в прошлом я был погуглить для подобной проблемы и нашел сценарий, который отметил все «сливаться» филиал вещи, как хорошо, поэтому, оставляя только слияние себя обязательства. –

+0

@BalogPal - Я видел подобную рекомендацию, но похоже, что это означало бы все в отрасли как хорошее, когда на самом деле она содержит плохую фиксацию. Для меня странно, что я не мог даже заставить биссект решить проблему слияния. Как ни странно, он решил совершить сделку, которая даже не была в пределах коммитов. – tollmanz

+0

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

ответ

-4

Вы можете выбрать диапазон коммитов с помощью команды «git start». Синопсис команды:

git bisect start <bad> <good> 

В вашем конкретном случае, я думаю, что правая команда будет:

git bisect start 3830e61 107ca95 
+2

Разве это не было бы эквивалентно подходу OP? – Basilevs

10

Это already answered

Основная идея - найти которые совершают от feature- ветвь ломает вашего хозяина, вам придется повторно применить его поверх ea3d736 - соответствующего мастера HEAD.

Ниже приведен пример (из git doc) тестового сценария, который делает это для вас:

$ cat ~/test.sh 
#!/bin/sh 

# tweak the working tree by merging the hot-fix branch 
# and then attempt a build 
if git merge --no-commit ea3d736 && 
    make 
then 
    # run project specific test and report its status 
    ~/check_test_case.sh 
    status=$? 
else 
    # tell the caller this is untestable 
    status=125 
fi 

# undo the tweak to allow clean flipping to the next commit 
git reset --hard 

# return control 
exit $status 

Выполнить это:

git bisect start 3830e61 f52cc34 
git bisect good ea3d736 17ca0bb #If you want to test feature branch only 
git bisect run ~/test.sh 
7

Это очень старый, но неотвеченный вопрос. Я решил исследовать и обнаружил, что могу показать, что поведение Git отличается от того, о чем говорит этот вопрос. Одним из объяснений является то, что Git улучшил алгоритм для bisect или что опросник совершил ошибку при маркировке.

Я пытаюсь узнать больше и git bisect, но у меня возникли проблемы с этой историей. Я знаю, что 107ca95 хорош и 3830e61 - это плохо. Когда я запускаю git bisect, коммиты 107ca95..3e667f8 игнорируются. Я знаю, что 43a07b1 - это фиксация, которая ввела регрессию, но никогда не оценивается.

Я написал код, чтобы проверить, оценивается он или нет. Мой тест показывает, что он оценивается. Выполните приведенный ниже код и убедитесь, что появляется сообщение с сообщением Add menu styles..

Дополнительные комментарии:

  • «совершает 107ca95..3e667f8 игнорируются»: Обратите внимание, что коммит вы отметили как «хороший» не будет оцениваться, так как мерзавец, уже знает, что это будет хорошо.
  • Пожалуйста, прочитайте раздел «Алгоритм бисекции» в this article by Christian Couder. Также может потребоваться раздел «Проверка оснований слияния».
  • Как упоминалось выше, вопрос, безусловно, использовался в другой версии, чем тот, который я использовал (вопрос с 2013 года, Git 2.11 - с 2016 года).

Bisect запустить выход

  • Обратите внимание, что первый «Добавить администратора уведомление» проверяется (строка 4), потому что обеспечивает наиболее полную информацию. (Прочитайте «Проверка оснований слияния» из статьи, упомянутой выше.)
  • С этого момента он делит пополам линейную историю, как и следовало ожидать.

# bad: [d7761d6f146eaca1d886f793ced4315539326866] Add data escaping. (Bad) 
# good: [f555d9063a25a20a6ec7c3b0c0504ffe0a997e98] Add Responsive Nav. (Good) 
git bisect start 'd7761d6f146eaca1d886f793ced4315539326866' 'f555d9063a25a20a6ec7c3b0c0504ffe0a997e98' 
# good: [1b3b7f4952732fec0c68a37d5f313d6f4219e4ae] Add ‘Admin’ notice. (Good) 
git bisect good 1b3b7f4952732fec0c68a37d5f313d6f4219e4ae 
# bad: [f9a65fe9e6cde4358e5b8ef7569332abfb07675e] Add icons. (Bad) 
git bisect bad f9a65fe9e6cde4358e5b8ef7569332abfb07675e 
# bad: [165b8a6e5137c40ce8b90911e59d7ec8eec30f46] Add menu styles. (Bad) 
git bisect bad 165b8a6e5137c40ce8b90911e59d7ec8eec30f46 
# first bad commit: [165b8a6e5137c40ce8b90911e59d7ec8eec30f46] Add menu styles. (Bad) 

Код

Run в Python 3 с Git 2.11.0. Команда для запуска: python3 script.py

""" The following code creates a git repository in '/tmp/git-repo' and populates 
it with the following commit graph. Each commit has a test.sh which can be used 
as input to a git-bisect-run. 

The code then tries to find the breaking change automatically. 
And prints out the git bisect log. 

Written in response to http://stackoverflow.com/questions/17267816/git-bisect-with-merged-commits 
to test the claim that '107ca95..3e667f8 are never checked out'. 

Needs Python 3! 
""" 


from itertools import chain 
import os.path 
import os 
import sh 

repo = { 
0x3830e61: {'message': "Add data escaping.", 'parents': [ 0x0f5e148 ], 'test': False} , # Last: (Bad) 
0x0f5e148: {'message': "Improve function for getting page template.", 'parents': [ 0xaaf8dc5], 'test': False}, 
0xaaf8dc5: {'message': "Merge branch 'navigation'", 'parents': [ 0x3e667f8, 0xea3d736], 'test': False}, 
    0x3e667f8: {'message': "Add icons.", 'parents': [ 0x43a07b1], 'test': False}, 
    0x43a07b1: {'message': "Add menu styles.", 'parents': [ 0x107ca95], 'test': False} , # First:  (Breaks) 
    0x107ca95: {'message': "Add Responsive Nav.", 'parents': [ 0xf52cc34], 'test': True}, # First:  (Good) 
    0xea3d736: {'message': "Add ‘Admin’ notice.", 'parents': [ 0x17ca0bb], 'test': True}, 
    0x17ca0bb: {'message': "Update placeholder text.", 'parents': [ 0xf52cc34], 'test': True}, 
0xf52cc34: {'message': "Add featured image.", 'parents': [ 0x2abd954], 'test': True}, 
0x2abd954: {'message': "Style placeholders.", 'parents': [], 'test': True}, 
} 

bad = 0x3830e61 
good = 0x107ca95 


def generate_queue(_dag, parents): 
    for prev in parents: 
     yield prev 
     yield from generate_queue(_dag, _dag[prev]['parents']) 

def make_queue(_dag, inits): 
    """ Converts repo (a DAG) into a queue """ 
    q = list(generate_queue(_dag, inits)) 
    q.reverse() 
    seen = set() 
    r = [x for x in q if not (x in seen or seen.add(x))] 
    return r 

if __name__ == '__main__': 
    pwd = '/tmp/git-repo' 
    sh.rm('-r', pwd) 
    sh.mkdir('-p', pwd) 
    g = sh.git.bake(_cwd=pwd) 
    g.init() 

    parents = set(chain.from_iterable((repo[c]['parents'] for c in repo))) 

    commits = set(repo) 
    inits = list(commits - parents) 
    queue = make_queue(repo, inits) 

    assert len(queue) == len(repo), "queue {} vs repo {}".format(len(queue), len(repo)) 

    commit_ids = {} 
    # Create commits 
    for c in queue: 
     # Set up repo 
     parents = repo[c]['parents'] 
     if len(parents) > 0: 
      g.checkout(commit_ids[parents[0]]) 
     if len(parents) > 1: 
      if len(parents) > 2: raise NotImplementedError('Octopus merges not support yet.') 
      g.merge('--no-commit', '-s', 'ours', commit_ids[parents[1]]) # just force to use 'ours' strategy. 

     # Make changes 
     with open(os.path.join(pwd, 'test.sh'), 'w') as f: 
      f.write('exit {:d}\n'.format(0 if repo[c]['test'] else 1)) 
     os.chmod(os.path.join(pwd, 'test.sh'), 0o0755) 
     with open(os.path.join(pwd, 'message'), 'w') as f: 
      f.write(repo[c]['message']) 
     g.add('test.sh', 'message') 
     g.commit('-m', '{msg} ({test})'.format(msg=repo[c]['message'], test='Good' if repo[c]['test'] else 'Bad')) 
     commit_ids[c] = g('rev-parse', 'HEAD').strip() 

    # Run git-bisect 
    g.bisect('start', commit_ids[bad], commit_ids[good]) 
    g.bisect('run', './test.sh') 
    print(g.bisect('log')) 
+0

Интересное расследование. +1. Не забывайте, что OP задал вопрос в 2013 году. «Git bisect», возможно, изменился с тех пор с более поздним (Q4 2016) git 2.11. – VonC

+0

@VonC, спасибо! Я написал это, но подчеркнул это сейчас. – Unapiedra