Làm cách nào để chọn chiến lược hợp nhất cho rebase git?


147

git-rebaseđề cập đến trang người đàn ông -X<option>có thể được thông qua git-merge. Khi nào / chính xác như thế nào?

Tôi muốn phản ứng lại bằng cách áp dụng các bản vá với chiến lược đệ quy và tùy chọn của chúng (áp dụng bất kỳ gậy nào, thay vì bỏ qua toàn bộ các cam kết xung đột). Tôi không muốn hợp nhất, tôi muốn làm cho lịch sử tuyến tính.

Tôi đã thử:

git rebase -Xtheirs

git rebase -s 'recursive -Xtheirs'

nhưng git từ chối -Xtrong cả hai trường hợp.


git rebase -Xtheirshoạt động trong các phiên bản gần đây, ngoại trừ xung đột cây cần được giải quyết bằng tay. Bạn cần chạy git rebase -Xtheirs --continue(với sự -Xlặp lại) sau khi giải quyết những xung đột đó.


Lưu ý: điều này bây giờ làm việc với git rebase --interactivequá. Xem [câu trả lời cập nhật của tôi dưới đây ( stackoverflow.com/a/2945367/6309 ).
VonC

Câu trả lời:


229

Bạn có thể sử dụng điều này với các phiên bản Git v1.7.3 trở lên.

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

(viết tắt git rebase --strategy recursive --strategy-option theirs ${branch}của tài liệu này )

Từ ghi chú phát hành Git v1.7.3:

git rebase --strategy <s>đã học tùy chọn --strategy-option/ -Xđể vượt qua các tùy chọn bổ sung được hiểu bởi chiến lược hợp nhất đã chọn.

NB: "Của chúng tôi" và "của họ" có nghĩa trái ngược với những gì họ làm trong một hợp nhất thẳng. Nói cách khác, "của họ" ủng hộ các cam kết trên nhánh hiện tại .


6
để làm rõ: $ git rebase - đệ quy chiến lược -X của họ
Gregg Lind

28
Khi tôi thử điều này, ý nghĩa của ourstheirsdường như trái ngược với những gì tôi mong đợi. Tôi cần sử dụng theirsđể ủng hộ chi nhánh hiện tại của tôi.
Craig McQueen

19
@CraigMcQueen, khi sử dụng rebase, các cam kết chưa được công bố (chưa được xử lý) của bạn được đặt sang một bên, nhánh được liên kết với điều khiển từ xa (chuyển tiếp nhanh) và các cam kết của bạn đang được phát lại trên đầu chi nhánh của bạn. . Cam kết của bạn là "của họ" theo hoạt động hợp nhất và trạng thái hiện tại (chuyển tiếp nhanh) của chi nhánh địa phương là "của chúng tôi". Có thể có vẻ phản trực giác, nhưng một khi bạn nhận ra những gì đang thực sự xảy ra, nó có ý nghĩa.
patrikbeno

6
@patrikbeno: Để trích dẫn Obi-Wan Kenobi, "Vì vậy, những gì tôi nói với bạn là đúng ... từ một quan điểm nhất định."
Craig McQueen

5
Tôi không chắc chắn rằng nó đáng để thêm, nhưng ít nhất trong các phiên bản tương đối hiện tại, sự hiện diện của -Xngụ ý -s recursive, vì vậy bây giờ bạn có thể sử dụng chỉ git rebase ${branch} -X theirs. (nguồn git-scm.com/docs/git-rebase#git-rebase--Xltstrargety-optiongt )
Matt Passell

20

Đây là chiến lược hợp nhất đi kèm với bộ tùy chọn của riêng họ

git rebase <branch> -s recursive -X theirs

nên hoạt động, mặc dù bản vá này đề cập (tháng 2 năm 2010):

Trang này nói rằng git-rebasehỗ trợ các chiến lược hợp nhất, nhưng lệnh rebase không biết -Xvà cung cấp cách sử dụng khi được trình bày cùng với nó.

Vì vậy, nếu nó vẫn không hoạt động, nó đang được tranh luận ngay bây giờ!
(được hỗ trợ trong git gần đây)


Cập nhật từ cam kết db2b3b820e2b28da268cc88adff076b394392dfe (tháng 7 năm 2013, git 1.8.4+),

Đừng bỏ qua các tùy chọn hợp nhất trong rebase tương tác

Chiến lược hợp nhất và các tùy chọn của nó có thể được chỉ định trong git rebase, nhưng với -- interactive, chúng hoàn toàn bị bỏ qua.

Đã ký tắt: Arnaud Fontaine

Điều đó có nghĩa là -Xvà chiến lược hiện đang hoạt động với rebase tương tác, cũng như rebase đơn giản.


1
@yheL: Tôi cũng nghĩ vậy. Do đó liên kết của tôi với đề xuất vá.
VonC

@yheL: Vâng, tôi cũng đã nhận thấy lỗi này - Tôi hy vọng nó sẽ được xử lý sớm, dù là với bản vá đó hay cách khác, vì tất cả các phương tiện cơ bản đều ở đó; họ chỉ cần quyết định chính xác cách họ sẽ giao tiếp từ rebase để hợp nhất.
Cascabel

@yheL: nó được bao gồm trong git 1.7.3. Nếu bạn vẫn là người dùng 1.7.1 như tôi, có một giải pháp dễ dàng, hãy kiểm tra câu trả lời của tôi bên dưới
MestreLion

7

Như iCrazy đã nói, tính năng này chỉ khả dụng cho git 1.7.3 trở đi. Vì vậy, đối với những linh hồn nghèo (như tôi) vẫn sử dụng 1.7.1, tôi trình bày một giải pháp tôi tự làm:

git-rebase-của họ

Đó là một tập lệnh được đánh bóng rất tốt (và do đó dài), có nghĩa là để sử dụng sản xuất: tùy chọn ui, xử lý nhiều tệp, kiểm tra xem tệp có thực sự có dấu xung đột hay không, nhưng "lõi" có thể được tóm tắt trong 2 dòng:

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

Và đây là kịch bản đầy đủ:

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

Cảm ơn @VonC! Tôi chỉ không chắc tại sao SO không mã hóa tập lệnh bash. Một kịch bản lớn như thế này luôn luôn xấu xí ... nhưng việc trở thành một khối lượng lớn văn bản đen khiến nó thậm chí còn xấu hơn: P
MestreLion

Nó được giải thích trong stackoverflow.com/editing-help#syntax-highlighting . Tôi đã thêm mã ngôn ngữ thích hợp trước khối mã của bạn. Nó sẽ nhìn tốt hơn bây giờ.
VonC

Cảm ơn @VonC! Làm nổi bật cú pháp của SO thực sự là phụ, nhưng nó tốt hơn không có gì. Và bạn cực kỳ chu đáo! Và, là THE authorithy git trong SO, bạn có thể quan tâm thêm một kịch bản helper: stackoverflow.com/a/10220276/624066 . Điều đó và tài khoản github của tôi có các công cụ bạn có thể thích.
MestreLion

Đối với 1.7.1, điều này dường như làm việc cho tôi; không cần kịch bản ở trên. git rebase --strategy="recursive --theirs" master
Papadeltasierra

Xin lỗi vì là người mới chơi git, nhưng làm thế nào để người ta sử dụng tập lệnh git-rebase-them được đưa ra ở trên? Đây có phải là một tùy chọn bằng cách nào đó được chuyển qua git-rebase hay nó chỉ làm giảm thời gian cần thiết để giải quyết xung đột bằng tay?
Papadeltasierra
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.