Setting the file. One moment.
Resolve · Resolve Merge Conflicts · github/gh-aw · Skills Docs
ContentsBack to the top of the page
(opens in a new tab)
resolve.sh
Shell · 146 lines · 4 KB
16 files touched by the current diff) for leftover git conflict-marker lines
17 (<<<<<<<, |||||||, =======, >>>>>>>) and exits non-zero listing any hits.
18 Run it after resolving mixed conflicts and before compiling, and as a
19 standalone pre-flight check any time a source workflow file may have been
20 merged manually — `git diff --check` only inspects changed hunks and will
21 not catch markers already committed in unchanged file content.
22 EOF
23 }
24
25 verify_markers () {
26 local repo_root
27 repo_root = $( git rev-parse --show-toplevel 2> /dev/null ) ||
28 die "run this command inside a Git repository"
29 cd " $repo_root "
30
31 local pattern = '^(<{7}|\|{7}|={7}|>{7})([^=<>|]|$)'
32 local hits = 0
33 while IFS = read -r -d '' file ; do
34 local matches
35 matches = $( grep -nE " $pattern " -- " $file " || true )
36 if [[ -n $matches ]]; then
37 hits = 1
38 echo "error: leftover conflict marker(s) in $file :" >&2
39 echo " $matches " >&2
40 fi
41 done < <( find .github/workflows -maxdepth 1 -name '*.md' -print0 2> /dev/null)
42
43 if (( hits )); then
44 die "unresolved conflict markers found in workflow source; fix before compiling"
45 fi
46 echo "No conflict markers found in .github/workflows/*.md"
47 }
48
49 die () {
50 echo "error: $* " >&2
51 exit 1
52 }
53
54 if [[ ${1 :- } == "--help" || ${1 :- } == "-h" ]]; then
55 usage
56 exit 0
57 fi
58 if [[ ${1 :- } == "--verify-markers" ]]; then
59 verify_markers
60 exit 0
61 fi
62 if (( $# > 1 )); then
63 usage >&2
64 exit 2
65 fi
66
67 base_ref = ${1 :- origin / main }
68 repo_root = $( git rev-parse --show-toplevel 2> /dev/null ) ||
69 die "run this command inside a Git repository"
70 cd " $repo_root "
71
72 merge_in_progress = false
73 if git rev-parse -q --verify MERGE_HEAD > /dev/null ; then
74 merge_in_progress = true
75 else
76 git rev-parse --verify "${ base_ref }^{commit}" > /dev/null 2>&1 ||
77 die "base ref ' $base_ref ' is unavailable; fetch it first if credentials are available"
78
79 if [[ -n $( git status --porcelain ) ]]; then
80 die "working tree must be clean before starting the merge"
81 fi
82
83 echo "Merging $base_ref without committing..."
84 if ! git merge --no-edit --no-commit " $base_ref " ; then
85 if ! git rev-parse -q --verify MERGE_HEAD > /dev/null ; then
86 die "merge failed before creating a resolvable merge state"
87 fi
88 merge_in_progress = true
89 fi
90 fi
91
92 mapfile -d '' conflicts < <( git diff --name-only --diff-filter=U -z )
93 non_lock_conflicts = ()
94 for path in "${ conflicts [ @ ]}" ; do
95 if [[ ! $path =~ ^ \. github/workflows/[^/]+ \. lock \. yml$ ]]; then
96 non_lock_conflicts += ( " $path " )
97 fi
98 done
99
100 if (( ${ # non_lock_conflicts[ @ ]} > 0 )); then
101 echo "Refusing automatic resolution; resolve these source conflicts first:" >&2
102 printf ' %s\n' "${ non_lock_conflicts [ @ ]}" >&2
103 exit 1
104 fi
105
106 if (( ${ # conflicts[ @ ]} > 0 )); then
107 echo "Regenerating ${ # conflicts [ @ ]} conflicted workflow lock file(s)..."
108 else
109 echo "No unresolved source conflicts; recompiling workflows..."
110 fi
111
112 # A manually resolved .md source conflict can silently leave behind a
113 # conflict-marker line (e.g. "|||||| base (original)") that git diff --check
114 # will not flag once staged/committed. Fail fast before compiling so the
115 # error surfaces here instead of during a later scheduled recompilation.
116 verify_markers
117
118 make recompile
119
120 if (( ${ # conflicts[ @ ]} > 0 )); then
121 git add -- "${ conflicts [ @ ]}"
122 fi
123
124 mapfile -d '' regenerated_locks < <(
125 git diff --name-only -z -- '.github/workflows/*.lock.yml'
126 )
127 if (( ${ # regenerated_locks[ @ ]} > 0 )); then
128 git add -- "${ regenerated_locks [ @ ]}"
129 fi
130
131 mapfile -d '' remaining < <( git diff --name-only --diff-filter=U -z )
132 if (( ${ # remaining[ @ ]} > 0 )); then
133 printf 'error: unresolved conflicts remain:\n' >&2
134 printf ' %s\n' "${ remaining [ @ ]}" >&2
135 exit 1
136 fi
137
138 git diff --check
139 git diff --cached --check
140
141 if [[ $merge_in_progress == true ]] ||
142 git rev-parse -q --verify MERGE_HEAD > /dev/null ; then
143 echo "Resolved and staged generated lock conflicts. Review and commit the merge."
144 else
145 echo "Merge and workflow recompilation complete. Review the working tree."
146 fi