forked from MestreLion/git-tools
-
Notifications
You must be signed in to change notification settings - Fork 6
/
git-rebase-theirs
executable file
·137 lines (111 loc) · 4 KB
/
git-rebase-theirs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/env 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 ; }
argerr() { printf "%s: %s\n" "$myname" "${1:-error}" >&2 ; usage 1 ; }
invalid() { argerr "invalid option: $1" ; }
missing() { argerr "missing${1:+ $1} operand." ; }
# Bash 4.4 does not allow 'continue' inside functions to operate on outer loops
# See https://stackoverflow.com/a/52497694/624066
skip() { message "skipping ${2:-$file}${1:+: $1}"; }
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, one may want to automatically resolve conflicts
by favoring the <working branch> version, which is the branch being
rebased, 'theirs' side in a rebase, instead of the <upstream> version,
the base branch, 'ours' side in the rebase.
The solution is 'git rebase --strategy recursive -X theirs', which is
only available since git 1.7.3. For older versions, $myname
solves that problem. And despite its name it's also useful for fixing
failed cherry-picks.
It works by discarding all lines between '<<<<<<< ' and '========',
inclusive, and also 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#*=}" ;;
-- ) shift ; break ;;
-* ) invalid "$1" ;;
* ) files+=( "$1" ) ;;
esac
shift
done
files+=( "$@" )
if ! (( "${#files[@]}" )); then missing "FILE"; fi
ext=${suffix:-$ext}
for file in "${files[@]}"; do
if ! [[ -f "$file" ]]; then skip "not a valid file"; continue; fi
if ((inplace)); then
outfile=$(mktemp) ||
{ skip "could not create temporary file"; continue; }
# shellcheck disable=SC2064
trap "rm -f -- '$outfile'" EXIT
cp "$file" "$outfile" || { skip; continue; }
exec 3>"$outfile"
else
exec 3>&1
fi
# Do the magic :)
awk '/^<<<<<<<+ .+$/,/^=+$/{next} /^>>>>>>>+ /{next} 1' "$file" >&3
exec 3>&-
if ! ((inplace)); then continue; fi
diff "$file" "$outfile" >/dev/null &&
{ skip "no conflict markers found"; continue; }
if ((backup)); then
cp "$file" "$file$ext" || { skip "could not backup"; continue; }
fi
cp "$outfile" "$file" || { skip "could not edit in-place"; continue; }
rm -f -- "$outfile"
trap - EXIT
if ((verbose)); then message "resolved ${file}"; fi
done