2013-06-24 16 views
32

ho una storia che assomiglia a questo:Git bisect con commit uniti

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

Sto cercando di saperne di più e git bisect, ma sto avendo problemi con questa storia. So che 107ca95 è buono e 3830e61 non funziona correttamente. Quando eseguo un git bisect, commit 107ca95..3e667f8 vengono ignorati. So che lo 43a07b1 è il commit che ha introdotto una regressione, ma non viene mai valutato.

Ecco più o meno quello che ho fatto:

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

Non importa quello che faccio, non sono mai 107ca95..3e667f8 estratto da testare.

C'è un modo in cui posso essenzialmente "appiattire" la storia durante il bisect per testare quei commit? So che posso usare uno rebase interattivo per appiattire la cronologia, ma non voglio farlo.

+0

in passato sono stato googling per un problema simile e ha trovato uno script che ha segnato tutta la roba ramo "merge" come buono, in modo da lasciare solo l'unione si impegni. –

+0

@BalogPal - Ho visto una raccomandazione simile, ma sembra che possa contrassegnare tutto nel ramo come buono, quando in realtà contiene un commit errato. La cosa strana per me è che non riuscivo nemmeno a convincere il bisect a risolvere il commit di fusione. Stranamente, ha risolto un commit che non era nemmeno nel range di commit. – tollmanz

+0

va bene, si esegue una bisettrice a 2 passaggi, se il primo identifica un'unione, quindi si bisecta che si unisca con i commit che ha. Ma se hai un'idea migliore, basta applicarla con la tecnologia, il punto è che puoi usare degli script per pre-marcare certi commit –

risposta

-4

È possibile selezionare l'intervallo di commit con il comando "git start". La sinossi del comando è:

git bisect start <bad> <good> 

Nel vostro caso specifico credo che il comando giusta sarebbe:

git bisect start 3830e61 107ca95 
+2

Non sarebbe equivavente per l'approccio dell'OP? – Basilevs

10

Questo è already answered

idea di base - per trovare quale commettere da Feature- il ramo spezza il tuo maestro, dovrai riapplicarlo sopra ea3d736 - maestro principale pertinente.

seguente è un esempio (da git doc) di script di test che fa per voi:

$ 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 

eseguirlo:

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

Questo è molto domanda vecchia ma senza risposta. Ho deciso di indagare e ho scoperto che potevo dimostrare che il comportamento di Git è diverso da quello che dice la domanda. Una spiegazione è che Git ha migliorato l'algoritmo per bisect o che l'interrogante ha commesso un errore nella marcatura dei commit.

Sto cercando di saperne di più e binario di bisect, ma sto avendo problemi con questa storia. So che 107ca95 è buono e 3830e61 non funziona correttamente. Quando eseguo un bisect git, commit 107ca95..3e667f8 vengono ignorati. Mi è capitato di sapere che 43a07b1 è il commit che ha introdotto una regressione, ma non viene mai valutato.

Ho scritto un codice per verificare se è stato valutato o meno. Il mio test mostra che è stato valutato. Eseguire il codice seguente e verificare che venga visualizzato un commit con il messaggio Add menu styles..

Ulteriori commenti:

  • "commette 107ca95..3e667f8 vengono ignorati": Si prega di notare, che il commit contrassegnato come "buono" di valutazione non sarà perché git sa già che fosse buono.
  • Leggere la sezione "Algoritmo di bisezione" in this article by Christian Couder. Anche la sezione "Controllo delle basi di fusione" potrebbe essere rilevante.
  • Come accennato in precedenza, la domanda era sicuramente utilizzando una versione diversa da quella che ho usato (la domanda è del 2013, Git 2.11 è del 2016).

bisect gestita uscita

  • Si noti che prima 'Aggiungi avviso Admin' è selezionata (linea 4), perché che fornisce la maggior parte delle informazioni. (Leggi "Controllo delle basi di fusione" dall'articolo menzionato sopra.)
  • Da quel momento in poi, divide in due la cronologia lineare come ci si aspetterebbe.

# 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) 

Codice

Run nella Python 3, con Git 2.11.0. Comando da eseguire: 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

Inchiesta interessante. +1. Non dimenticare che l'OP ha scritto la domanda nel 2013. 'git bisect' potrebbe essere cambiato da allora con il più recente (Q4 2016) git 2.11. – VonC

+0

@VonC, grazie! L'avevo scritto ma l'ho enfatizzato ora. – Unapiedra