-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgit-base
executable file
·224 lines (180 loc) · 4.25 KB
/
git-base
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/usr/bin/tclsh
set la ""
set ia ""
foreach val $argv {
if { $val == "--/" } {
set la ""
continue
}
if { [string range $val 0 1] == "--" } {
set la [string range $val 2 end]
set ::options($la) ""
continue
}
if { $la != "" } {
lappend ::options($la) $val
continue
}
# If not for-option and not option, then free args.
lappend ia $val
}
if { [llength $ia] > 1 } {
"Usage: git base \[branch\] <options...>"
exit 1
}
proc option {name {default ""}} {
if {[info exists ::options($name)]} {
return $::options($name)
}
return $default
}
set mbranch $ia
if {$mbranch == ""} {
set mbranch [exec git branch --show-current]
if {$mbranch == ""} {
puts stderr "ERROR: Detached head state. The branch must be explicitly specified"
exit 1
}
}
set refloginfo [exec git reflog show $mbranch {--pretty=format:%H %gd {%D}}]
set all_remotes [exec git remote]
set reflogdata ""
foreach i [split $refloginfo \n] {
lassign $i hid refmark branchinfo
lassign [split $refmark @] mbr ord
set brlist [split $branchinfo ,]
set markhead ""
set sidebr ""
foreach b $brlist {
set b [string trim $b]
lassign [regexp -inline {([^ ]*) -> ([^ ]*)} $b] unu hd br
if {$unu != ""} {
if {$hd == "HEAD"} {
set markhead "="
}
} else {
set br $b
}
if { [string range $br 0 4] == "tag: " } {
set br "" ;# ignore tags
}
set isrem 0
# Now check if the branch is remote
set brparts [file split $br]
if {[llength $brparts] > 1} {
# Name with slash; check if the first part is remote.
# If so, it's a remote branch
set rname [lindex $brparts 0]
if {$rname == "remotes" || $rname in $all_remotes} {
set isrem 1
}
}
if {!$isrem && $sidebr == ""} {
set sidebr $br
}
}
lappend reflogdata $hid ${markhead}$sidebr
}
# May check the parent information, if necessary:
#set parents [exec git rev-list --parents -n 5 $headcommit]
# foreach l [split $parents \n] {
# puts "\[[lindex $l 0]\] -> [lrange $l 1 end]"
# }
# Display - for debugging
# Note: with --all, all other options are ignored, except debug
set is_debug [expr {[option debug -] != "-"}]
if {[option all -] != "-"} {
# Walk through the list, skip those that have
# the head branch (= in the name) or no branch info.
# Display all others, in the right order.
set first 1
foreach {hid br} $reflogdata {
if {$first} {
# Skip the very first entry, it's the branch's head.
set first 0
continue
}
if {$br == ""} {
continue
}
if {$is_debug} {
puts "$hid : $br"
} else {
puts $hid
}
}
exit 0
}
if {$is_debug} {
foreach {hid br} $reflogdata {
if {$br == ""} {
puts "$hid (continued)"
} else {
puts "$hid : $br"
}
}
exit 0
}
# Search for the first found with branch marker, just not head.
set first [option first -]
if {$first != "-"} {
set first 1
foreach {hid br} $reflogdata {
if {$first} {
# Skip the very first entry, it's the branch's head.
set first 0
continue
}
if {$br == ""} {
continue
}
puts $hid
exit 0
}
puts stderr "NOTE: no commit found merged from '$reqbase'"
exit 0
}
set reqbase [option off]
# This option defines, which branch is considered the parent branch.
# If defined, this branch will be searched in the list. Otherwise first
# found will be considered the direct base.
# If not, look at the BOTTOM of the list to see if you have the first branch
# (default mode)
if {$reqbase == ""} {
set reqbase [lindex $reflogdata end]
if {$reqbase == ""} {
set hdbr [lindex $reflogdata 1]
if {[string index $hdbr 0] == "="} {
set hdbr [string range $hdbr 1 end]
} else {
set hdbr "(unknown)"
}
puts stderr "NOTE: No draw-off information found for '$mbranch' walking from '$hdbr'"
exit 1
}
}
# Just in case, read the reflog information from this name.
set reqbase_reflog [exec git reflog show $reqbase --pretty=format:%H]
set first 1
foreach {hid br} $reflogdata {
if {$first} {
# Skip the very first entry, it's the branch's head.
set first 0
continue
}
if {$br == ""} {
# Check that maybe this hash is in the reqbase reflog
# XXX CHECK ITS CHILD COMMIT, NOT IT ITSELF!
if {$hid in $reqbase_reflog} {
set br $reqbase
} else {
continue
}
}
if {$br == $reqbase} {
puts $hid
exit 0
}
}
puts stderr "NOTE: no commit found merged from '$reqbase'"
exit 0