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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//! Typed failures for history rewrite planning.
use crate::error::Error;
use crate::objects::ObjectId;
use thiserror::Error;
/// Failure modes while building a [`super::RewritePlan`](crate::history::RewritePlan).
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum HistoryError {
/// Underlying object database, revision walk, or ref operation failed.
#[error(transparent)]
Library(Box<Error>),
/// The replacement commit message is empty after whitespace cleanup.
#[error("commit message cannot be empty")]
EmptyMessage,
/// [`super::reword::reword_with`](crate::history::reword::reword_with) needs a message and/or author change.
#[error("reword requires a new message or author")]
NothingToReword,
/// Author argument could not be parsed (`Name <email>` or bare email).
#[error("{0}")]
InvalidAuthor(#[from] crate::ident::AuthorArgError),
/// [`super::fixup`](crate::history::fixup) requires a working tree and index.
#[error("history fixup cannot run in a bare repository")]
BareRepository,
/// No staged changes relative to `HEAD`'s tree.
#[error("nothing to fixup: no staged changes")]
NothingStaged,
/// Hunk id or line-range selection failed before planning changed refs.
#[error(transparent)]
HunkSelect(#[from] crate::porcelain::hunk_select::HunkSelectError),
/// Applying staged changes onto the target would make that commit empty.
#[error("fixup makes commit {commit} empty")]
FixupMakesTargetEmpty {
/// Target commit that would become empty.
commit: ObjectId,
},
/// A pathspec split selected no changes from the target commit.
#[error("pathspec did not select any changes from the commit")]
SplitSelectsNothing,
/// A pathspec split selected every change in the target commit.
#[error("pathspec selected every change in the commit")]
SplitSelectsEverything,
/// Object database, revwalk, or other repository read failed during planning.
#[error("history rewrite planning failed: {message}")]
Planning {
/// Underlying failure summary.
message: String,
},
/// `InsertBefore` was requested on a merge commit.
#[error("insert-before on merge commit {commit} is not supported")]
InsertBeforeOnMerge {
/// Merge commit that cannot receive an insert-before edit.
commit: ObjectId,
},
/// A three-way replay produced unmerged paths.
#[error("replay of commit {commit} produced conflicts")]
Conflict {
/// Original commit that could not be replayed cleanly.
commit: ObjectId,
/// Repository-relative paths that conflicted.
paths: Vec<String>,
},
/// A merge commit cannot be dropped, reordered, or otherwise edited in an unsupported way.
#[error("merge commit {commit} cannot be dropped or reordered in this rewrite")]
MergeCommitInReplay {
/// Merge commit that cannot be replayed.
commit: ObjectId,
},
/// A root commit was dropped or otherwise needs a missing parent.
#[error("root commit {commit} cannot be dropped or replayed without a parent")]
RootCommit {
/// Root commit involved in the error.
commit: ObjectId,
},
/// Empty-policy [`super::EmptyPolicy::Abort`](crate::history::EmptyPolicy::Abort) tripped.
#[error("commit {commit} became empty after replay")]
BecameEmpty {
/// Commit that would become empty.
commit: ObjectId,
},
/// An edited commit is not on the history reachable from the active scope.
#[error("commit {commit} is not reachable from HEAD for this rewrite scope")]
NotInHistory {
/// Commit named in the edit map but outside scope.
commit: ObjectId,
},
/// A move anchor is not on the first-parent chain of `HEAD`.
#[error("commit {commit} is not on the linear first-parent history of HEAD")]
MoveTargetNotInHistory {
/// Anchor commit that is missing from the chain.
commit: ObjectId,
},
/// The move would leave commit order unchanged.
#[error("commit {commit} is already at the requested position")]
NoOp {
/// Commit that would not move.
commit: ObjectId,
},
/// Commits are not on the same first-parent chain or a merge sits in the segment.
#[error("history move requires a linear first-parent range without merge commits")]
NotLinear,
/// A scoped branch tip is not on the ancestry path being rewritten.
#[error("branch {name} diverged before the rewritten commits and cannot be updated")]
DivergentBranch {
/// Short or full branch name (`refs/heads/...`).
name: String,
},
/// Another linked worktree has this branch checked out.
#[error("branch {name} is checked out in worktree {worktree}")]
BranchCheckedOutElsewhere {
/// Branch ref short or full name.
name: String,
/// Path to the blocking worktree.
worktree: String,
},
/// Commit signing failed while writing a replacement commit object.
#[error("commit signing failed: {message}")]
Signing {
/// Underlying signing or config failure summary.
message: String,
},
/// Applying the plan would overwrite staged or unstaged worktree changes on affected paths.
#[error("local changes would be overwritten")]
LocalChangesWouldBeOverwritten {
/// Repository-relative paths that block the checkout.
paths: Vec<String>,
},
/// The index or worktree differs from `HEAD` before `rebase --exec` runs.
#[error("you have uncommitted changes — commit them before rebasing with --exec")]
UncommittedChanges,
/// A `rebase --exec` command exited non-zero; repository state was restored.
#[error("rebase --exec command failed at commit {commit} (exit {exit_code})")]
ExecFailed {
/// Replacement commit that was checked out when the command failed.
commit: ObjectId,
/// Subprocess exit code.
exit_code: i32,
/// Subprocess stdout from the failing command.
stdout: Vec<u8>,
/// Subprocess stderr from the failing command.
stderr: Vec<u8>,
/// Successful `--exec` runs before the failure (stdout/stderr captured).
completed_runs: Vec<super::ExecRunRecord>,
},
/// Selected commits do not form one connected component with allowed parents.
#[error("the selected commits are not a connected revision range")]
RangeNotConnected,
/// More than one tip commit appears in the selected range.
#[error("the revision range contains more than one tip commit")]
MultipleTips,
/// A fixup/amend/squash commit targets a commit outside the range.
#[error("cannot squash {commit}: its fixup/amend/squash target is outside the range")]
MarkerTargetOutsideRange {
/// Marker commit that could not be folded.
commit: ObjectId,
},
/// A `squash!` commit would lose its message without combining interactively.
#[error("squashing {commit} would discard its message; use --combine or -m")]
SquashDiscardsMessage {
/// Commit whose message would be dropped.
commit: ObjectId,
},
/// A planned ref no longer matches the stored value (compare-and-swap failure).
#[error("ref {name} changed since the rewrite plan was built")]
RefCasMismatch {
/// Ref that failed the expected-old check.
name: String,
},
/// `HEAD` no longer points at the ref or commit recorded in the plan.
#[error("HEAD moved since the rewrite plan was built")]
HeadMovedSincePlan {
/// Ref `HEAD` pointed at when planning, if symbolic.
planned_ref: Option<String>,
/// Commit `HEAD` pointed at when planning.
planned_commit: ObjectId,
},
/// Ref storage rejected the update batch.
#[error("ref update failed: {message}")]
RefApply {
/// Backend error summary.
message: String,
},
/// Index or worktree update failed after refs were already moved.
#[error("worktree update failed: {message}")]
WorktreeApply {
/// Underlying failure.
message: String,
},
/// No `.git/grit/history-last` record exists.
#[error("no history rewrite to undo")]
NoUndoRecord,
/// A ref or `HEAD` moved since the recorded rewrite.
#[error("ref {name} changed since the last history rewrite — undo is no longer safe")]
UndoStale {
/// Ref that no longer matches the recorded post-rewrite tip.
name: String,
},
/// Failed to read `.git/grit/history-last`.
#[error("could not read history undo record: {message}")]
UndoRecordRead {
/// Parse or I/O failure summary.
message: String,
},
/// Failed to write `.git/grit/history-last`.
#[error("could not write history undo record: {message}")]
UndoRecordWrite {
/// I/O or lock failure summary.
message: String,
},
/// Checkout failed after refs were updated; rollback or worktree restore may also have failed.
#[error("checkout failed after refs were updated")]
ApplyRollbackIncomplete {
/// Primary checkout failure.
checkout: String,
/// Ref rollback error, when rolling back failed.
ref_rollback: Option<String>,
/// Worktree/index restore error after checkout failed.
worktree_restore: Option<String>,
},
}