Як вибрати стратегію злиття для git rebase?


147

git-rebaseзгадки чоловічої сторінки -X<option>можуть бути передані до git-merge. Коли / як саме?

Я хотів би перезавантажити, застосувавши патчі з рекурсивною стратегією та їх варіантом (застосувати будь-які палички, а не пропускати цілі конфліктні коміти). Я не хочу злиття, я хочу зробити історію лінійною.

Я спробував:

git rebase -Xtheirs

і

git rebase -s 'recursive -Xtheirs'

але git відхиляє -Xв обох випадках.


git rebase -Xtheirsпрацює в останніх версіях, крім конфліктів з деревами потрібно вирішувати вручну. Після вирішення цих конфліктів потрібно бігти git rebase -Xtheirs --continue-Xповторним).


Примітка: і зараз це працює git rebase --interactive. Дивіться мою [оновлену відповідь нижче ( stackoverflow.com/a/2945367/6309 ).
VonC

Відповіді:


230

Ви можете використовувати це з версіями Git v1.7.3 або новіших версій.

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

(що є коротким, git rebase --strategy recursive --strategy-option theirs ${branch}як зазначено в документації )

З Git v1.7.3 Примітки до випуску:

git rebase --strategy <s>вивчив --strategy-option/ -Xваріант передавати додаткові параметри, які розуміються в обраній стратегії злиття.

NB: "Наші" та "їхні" означають протилежне тому, що вони роблять під час прямого злиття. Іншими словами, "їхнє" надає перевагу комітетам у поточній галузі.


6
уточнити: $ git rebase - стратегія рекурсивна -X їхня
Грегг Лінд

28
Коли я це намагаюся, сенс oursі, theirsздається, протилежний тому, що я очікую. Мені потрібно скористатися, theirsщоб віддати перевагу моїй нинішній галузі.
Крейг МакКуїн

19
@CraigMcQueen, коли використовується ребаза, ваші неопубліковані (незапущені) комісії відкладаються, гілка вирівнюється з віддаленою (швидкою переадресацією), а ваші комітети відтворюються поверх вашої гілки. . Ваші зобов’язання є "їхніми" відповідно до операції злиття, а поточний (швидкий напрямок) стан місцевого відділення - "наш". Це може здатися контрутуючим, але як тільки ви зрозумієте, що насправді відбувається, це має сенс.
патрикбено

6
@patrikbeno: Цитуючи Оби-Вана Кенобі, "Отже, те, що я вам сказав, було правдою ... з певної точки зору".
Крейг МакКуїн

5
Я не впевнений, що варто додати, але принаймні у відносно поточних версіях наявність -Xприпущень -s recursive, тому тепер можна використовувати просто git rebase ${branch} -X theirs. (джерело git-scm.com/docs/git-rebase#git-rebase--Xltstrategy-optiongt )
Метт Пассел

20

Це для стратегій злиття, які поставляються із власним набором варіантів

git rebase <branch> -s recursive -X theirs

має працювати, хоча цей патч згадує (лютий 2010 р.):

На сторінці вказується, що git-rebaseпідтримує стратегії злиття, але команда rebase не знає про це -Xі дає використання при поданні з нею.

Тож якщо це все ще не працює, воно зараз обговорюється!
(підтримується нещодавно git)


Оновлення від комісії db2b3b820e2b28da268cc88adff076b396392dfe (липень 2013 року, git 1.8.4+),

Не ігноруйте параметри злиття в інтерактивній базі даних

Стратегію злиття та її варіанти можна вказати в git rebase, але з -- interactive, вони були повністю проігноровані.

Підписався: Арно Фонтен

Це означає, що -Xстратегія зараз працює з інтерактивною базою даних, а також з простою базою даних.


1
@porneL: Я так вважав. Звідси моє посилання на пропозицію про виправлення.
VonC

@porneL: Так, я помітив і цю помилку - я сподіваюся, що вона буде вирішена недовго, хоча б із цим патчем чи іншим чином, оскільки всі основні засоби є там; вони просто повинні вирішити, як саме вони збираються спілкуватися від rebase до об'єднання.
Каскабель

@porneL: він був включений у git 1.7.3. Якщо ви все ще користувач 1.7.1, як я, є просте рішення, перевірте мою відповідь нижче
MestreLion

7

Як сказав iCrazy , ця функція доступна лише для git 1.7.3. Отже, для бідних душ (як я), які все ще використовують 1.7.1, я пропоную рішення, яке я зробив сам:

git-rebase - їхнє

Це дуже добре відшліфований (і, таким чином, тривалий) сценарій, призначений для виробничого використання: параметри інтерфейсу, обробляє кілька файлів, перевіряють, чи файл насправді має конфліктні маркери тощо, але "ядро" може бути зведене у 2 рядки:

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

І ось повний сценарій:

#!/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

Дякую @VonC! Я просто не впевнений, чому так не зашифровано кольором сценарій bash. Великий подібний сценарій завжди потворний сам по собі ... але те, що величезна маса чорного тексту робить його ще більш потворним: P
MestreLion

Це пояснюється в stackoverflow.com/editing-help#syntax-highlighting . Я додав відповідний код вподобаної мови перед блоком коду. Це має виглядати зараз краще.
VonC

Дякую @VonC! Підсвічування синтаксису SO - це справді підрозділ, але це waaaay краще, ніж нічого. І ти надзвичайно продуманий! І, будучи THE git authorithy в SO, вас може зацікавити ще один помічник сценарію: stackoverflow.com/a/10220276/624066 . У цьому та моєму обліковому записі github є інструменти, якими ви можете користуватися.
MestreLion

Для 1.7.1 це, здається, працює для мене; немає необхідності в сценарії вище. git rebase --strategy="recursive --theirs" master
Papadeltasierra

Вибачте за те, що ви є початківцем git, але як використовується сценарій git-rebase -s, наведений вище? Це варіант якимось чином передається git-rebase чи це просто скорочує час, необхідний для ручного вирішення конфліктів?
Papadeltasierra
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.