Come faccio a selezionare una strategia di unione per un rebase git?


147

git-rebasele menzioni della pagina man -X<option>possono essere passate a git-merge. Quando / come esattamente?

Vorrei ribattere applicando patch con strategia ricorsiva e la loro opzione (applica qualunque stick, invece di saltare interi commit in conflitto). Non voglio unirmi, voglio rendere la storia lineare.

Ho provato:

git rebase -Xtheirs

e

git rebase -s 'recursive -Xtheirs'

ma git rifiuta -Xin entrambi i casi.


git rebase -Xtheirsfunziona nelle versioni recenti, ad eccezione dei conflitti di alberi che devono essere risolti manualmente. È necessario eseguire git rebase -Xtheirs --continue(con -Xripetuti) dopo aver risolto tali conflitti.


Nota: ora funziona git rebase --interactiveanche con questo. Vedi la mia [risposta aggiornata di seguito ( stackoverflow.com/a/2945367/6309 ).
VonC,

Risposte:


231

Puoi usarlo con Git v1.7.3 o versioni successive.

git rebase --strategy-option theirs ${branch} # Long option
git rebase -X theirs ${branch} # Short option

(che è l'abbreviazione di git rebase --strategy recursive --strategy-option theirs ${branch}come indicato nella documentazione )

Dalle note di rilascio di Git v1.7.3:

git rebase --strategy <s>imparato l' opzione --strategy-option/ -Xper passare opzioni extra che sono comprese dalla strategia di unione prescelta.

NB: "I nostri" e "loro" significano l'opposto di ciò che fanno durante una fusione diretta. In altre parole, "loro" favorisce gli commit sull'attuale ramo.


6
per chiarire: $ git rebase --strategy ricorsivo -X loro
Gregg Lind

28
Quando provo questo, il significato di ourse theirssembra essere l'opposto di quello che mi aspetto. Devo usare theirsper favorire la mia filiale attuale.
Craig McQueen,

19
@CraigMcQueen, quando si utilizza rebase, i commit non pubblicati (non caricati) vengono messi da parte, il ramo viene allineato con remoto (avanzamento rapido) e i commit vengono riprodotti in cima al ramo. . I tuoi commit sono "loro" in base all'operazione di unione e lo stato corrente (avanzamento rapido) della filiale locale è "nostro". Può sembrare controintuitivo, ma una volta realizzato ciò che sta realmente accadendo, ha senso.
patrikbeno,

6
@patrikbeno: Per citare Obi-Wan Kenobi, "Quindi quello che ti ho detto era vero ... da un certo punto di vista."
Craig McQueen,

5
Non sono sicuro che valga la pena aggiungere, ma almeno nelle versioni relativamente attuali, la presenza di -Ximplica -s recursive, quindi ora puoi usare solo git rebase ${branch} -X theirs. (fonte git-scm.com/docs/git-rebase#git-rebase--Xltstrategy-optiongt )
Matt Passell

20

Questo è per le strategie di unione che vengono con il proprio set di opzioni

git rebase <branch> -s recursive -X theirs

dovrebbe funzionare, sebbene questa patch menzioni (febbraio 2010):

La manpage dice che git-rebasesupporta le strategie di unione, ma il comando rebase non lo sa -Xe fornisce l'uso quando viene presentato con esso.

Quindi se ancora non funziona, si sta discutendo proprio ora!
(supportato in git recente)


Aggiornamento da commit db2b3b820e2b28da268cc88adff076b396392dfe (luglio 2013, git 1.8.4+),

Non ignorare le opzioni di unione in rebase interattivo

La strategia di unione e le sue opzioni possono essere specificate in git rebase, ma con -- interactive, sono state completamente ignorate.

Firmato-fuori-da: Arnaud Fontaine

Ciò significa -Xche la strategia ora funziona con rebase interattivo, nonché con rebase semplice.


1
@porneL: L'ho pensato. Da qui il mio link alla proposta di patch.
VonC,

@porneL: Sì, ho notato anche questo bug - mi aspetto che verrà risolto molto presto, sia con quella patch o altro, dal momento che tutte le strutture di base sono lì; devono solo decidere esattamente come comunicare da rebase a fusione.
Cascabel,

@porneL: è stato incluso in git 1.7.3. Se sei ancora un utente 1.7.1 come me, c'è una soluzione semplice, controlla la mia risposta qui sotto
MestreLion

7

Come diceva iCrazy , questa funzione è disponibile solo da git 1.7.3 in poi. Quindi, per le anime povere (come me) che usano ancora la 1.7.1, presento una soluzione che ho fatto io:

git-rebase-loro

È uno script molto ben rifinito (e quindi lungo), pensato per l'uso in produzione: opzioni dell'interfaccia utente, gestisce più file, controlla se il file ha effettivamente dei marker di conflitto, ecc., Ma il "core" potrebbe essere riassunto in 2 righe:

cp file file.bak
awk '/^<+ HEAD$/,/^=+$/{next} /^>+ /{next} 1' file.bak > file

Ed ecco lo script completo:

#!/bin/bash
#
# git-rebase-theirs - Resolve rebase conflicts by favoring 'theirs' version
#
#    Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program. If not see <http://www.gnu.org/licenses/gpl.html>

#Defaults:
verbose=0
backup=1
inplace=0
ext=".bak"

message() { printf "%s\n" "$1" >&2 ; }
skip()    { message "skipping ${2:-$file}${1:+: $1}"; continue ; }
argerr()  { printf "%s: %s\n" "$myname" "${1:-error}" >&2 ; usage 1 ; }
invalid() { argerr "invalid option: $1" ; }
missing() { argerr "missing${1:+ $1} operand." ; }

usage() {
    cat <<- USAGE
    Usage: $myname [options] [--] FILE...
    USAGE
    if [[ "$1" ]] ; then
        cat >&2 <<- USAGE
        Try '$myname --help' for more information.
        USAGE
        exit 1
    fi
    cat <<-USAGE

    Resolve git rebase conflicts in FILE(s) by favoring 'theirs' version

    When using git rebase, conflicts are usually wanted to be resolved
    by favoring the <working branch> version (the branch being rebased,
    'theirs' side in a rebase), instead of the <upstream> version (the
    base branch, 'ours' side)

    But git rebase --strategy -X theirs is only available from git 1.7.3
    For older versions, $myname is the solution.

    It works by discarding all lines between '<<<<<<< HEAD' and '========'
    inclusive, and also the the '>>>>>> commit' marker.

    By default it outputs to stdout, but files can be edited in-place
    using --in-place, which, unlike sed, creates a backup by default.

    Options:
      -h|--help            show this page.
      -v|--verbose         print more details in stderr.

      --in-place[=SUFFIX]  edit files in place, creating a backup with
                           SUFFIX extension. Default if blank is ""$ext"

       --no-backup         disables backup

    Copyright (C) 2012 Rodrigo Silva (MestreLion) <linux@rodrigosilva.com>
    License: GPLv3 or later. See <http://www.gnu.org/licenses/gpl.html>
    USAGE
    exit 0
}
myname="${0##*/}"

# Option handling
files=()
while (( $# )); do
    case "$1" in
    -h|--help     ) usage            ;;
    -v|--verbose  ) verbose=1        ;;
    --no-backup   ) backup=0         ;;
    --in-place    ) inplace=1        ;;
    --in-place=*  ) inplace=1
                    suffix="${1#*=}" ;;
    -*            ) invalid "$1"     ;;
    --            ) shift ; break    ;;
    *             ) files+=( "$1" )  ;;
    esac
    shift
done
files+=( "$@" )

(( "${#files[@]}" )) || missing "FILE"

ext=${suffix:-$ext}

for file in "${files[@]}"; do

    [[ -f "$file" ]] || skip "not a valid file"

    if ((inplace)); then
        outfile=$(tempfile) || skip "could not create temporary file"
        trap 'rm -f -- "$outfile"' EXIT
        cp "$file" "$outfile" || skip
        exec 3>"$outfile"
    else
        exec 3>&1
    fi

    # Do the magic :)
    awk '/^<+ HEAD$/,/^=+$/{next} /^>+ /{next} 1' "$file" >&3

    exec 3>&-

    ((inplace)) || continue

    diff "$file" "$outfile" >/dev/null && skip "no conflict markers found"

    ((backup)) && { cp "$file" "$file$ext" || skip "could not backup" ; }

    cp "$outfile" "$file" || skip "could not edit in-place"

    ((verbose)) && message "resolved ${file}"
done

Grazie @VonC! Non sono sicuro del perché SO non abbia codificato il colore dello script bash. Una grande sceneggiatura come questa è sempre brutta da sola ... ma essendo un'enorme massa di testo nero la rende ancora più brutta: P
MestreLion

È spiegato in stackoverflow.com/editing-help#syntax-highlighting . Ho aggiunto il codice lingua prettify appropriato prima del tuo blocco di codice. Dovrebbe apparire meglio ora.
VonC,

Grazie @VonC! L'evidenziazione della sintassi di SO è davvero scadente, ma è sicuramente meglio di niente. E sei estremamente premuroso! E, essendo L'authorithy git in SO, si può essere interessati in un altro script di aiuto: stackoverflow.com/a/10220276/624066 . Questo e il mio account Github hanno strumenti che potrebbero piacerti.
MestreLion,

Per 1.7.1, questo sembra funzionare per me; non è necessario per lo script sopra. git rebase --strategy="recursive --theirs" master
Papadeltasierra,

Ci scusiamo per essere un novizio git, ma come si usa lo script git-rebase-theirs di cui sopra? È un'opzione in qualche modo passata a git-rebase o riduce semplicemente il tempo necessario per risolvere manualmente i conflitti?
Papadeltasierra,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.