1 #define USE_THE_REPOSITORY_VARIABLE
10 #include "wildmatch.h"
14 #include "parse-options.h"
16 #define BUILTIN_REFLOG_SHOW_USAGE \
17 N_("git reflog [show] [<log-options>] [<ref>]")
19 #define BUILTIN_REFLOG_LIST_USAGE \
22 #define BUILTIN_REFLOG_EXISTS_USAGE \
23 N_("git reflog exists <ref>")
25 #define BUILTIN_REFLOG_WRITE_USAGE \
26 N_("git reflog write <ref> <old-oid> <new-oid> <message>")
28 #define BUILTIN_REFLOG_DELETE_USAGE \
29 N_("git reflog delete [--rewrite] [--updateref]\n" \
30 " [--dry-run | -n] [--verbose] <ref>@{<specifier>}...")
32 #define BUILTIN_REFLOG_DROP_USAGE \
33 N_("git reflog drop [--all [--single-worktree] | <refs>...]")
35 #define BUILTIN_REFLOG_EXPIRE_USAGE \
36 N_("git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n" \
37 " [--rewrite] [--updateref] [--stale-fix]\n" \
38 " [--dry-run | -n] [--verbose] [--all [--single-worktree] | <refs>...]")
40 static const char *const reflog_show_usage
[] = {
41 BUILTIN_REFLOG_SHOW_USAGE
,
45 static const char *const reflog_list_usage
[] = {
46 BUILTIN_REFLOG_LIST_USAGE
,
50 static const char *const reflog_exists_usage
[] = {
51 BUILTIN_REFLOG_EXISTS_USAGE
,
55 static const char *const reflog_write_usage
[] = {
56 BUILTIN_REFLOG_WRITE_USAGE
,
60 static const char *const reflog_delete_usage
[] = {
61 BUILTIN_REFLOG_DELETE_USAGE
,
65 static const char *const reflog_drop_usage
[] = {
66 BUILTIN_REFLOG_DROP_USAGE
,
70 static const char *const reflog_expire_usage
[] = {
71 BUILTIN_REFLOG_EXPIRE_USAGE
,
75 static const char *const reflog_usage
[] = {
76 BUILTIN_REFLOG_SHOW_USAGE
,
77 BUILTIN_REFLOG_LIST_USAGE
,
78 BUILTIN_REFLOG_EXISTS_USAGE
,
79 BUILTIN_REFLOG_WRITE_USAGE
,
80 BUILTIN_REFLOG_DELETE_USAGE
,
81 BUILTIN_REFLOG_DROP_USAGE
,
82 BUILTIN_REFLOG_EXPIRE_USAGE
,
86 struct worktree_reflogs
{
87 struct worktree
*worktree
;
88 struct string_list reflogs
;
91 static int collect_reflog(const char *ref
, void *cb_data
)
93 struct worktree_reflogs
*cb
= cb_data
;
94 struct worktree
*worktree
= cb
->worktree
;
95 struct strbuf newref
= STRBUF_INIT
;
98 * Avoid collecting the same shared ref multiple times because
99 * they are available via all worktrees.
101 if (!worktree
->is_current
&&
102 parse_worktree_ref(ref
, NULL
, NULL
, NULL
) == REF_WORKTREE_SHARED
)
105 strbuf_worktree_ref(worktree
, &newref
, ref
);
106 string_list_append_nodup(&cb
->reflogs
, strbuf_detach(&newref
, NULL
));
111 static int expire_unreachable_callback(const struct option
*opt
,
115 struct reflog_expire_options
*opts
= opt
->value
;
117 BUG_ON_OPT_NEG(unset
);
119 if (parse_expiry_date(arg
, &opts
->expire_unreachable
))
120 die(_("invalid timestamp '%s' given to '--%s'"),
121 arg
, opt
->long_name
);
123 opts
->explicit_expiry
|= REFLOG_EXPIRE_UNREACH
;
127 static int expire_total_callback(const struct option
*opt
,
131 struct reflog_expire_options
*opts
= opt
->value
;
133 BUG_ON_OPT_NEG(unset
);
135 if (parse_expiry_date(arg
, &opts
->expire_total
))
136 die(_("invalid timestamp '%s' given to '--%s'"),
137 arg
, opt
->long_name
);
139 opts
->explicit_expiry
|= REFLOG_EXPIRE_TOTAL
;
143 static int cmd_reflog_show(int argc
, const char **argv
, const char *prefix
,
144 struct repository
*repo UNUSED
)
146 struct option options
[] = {
150 parse_options(argc
, argv
, prefix
, options
, reflog_show_usage
,
151 PARSE_OPT_KEEP_DASHDASH
| PARSE_OPT_KEEP_ARGV0
|
152 PARSE_OPT_KEEP_UNKNOWN_OPT
);
154 return cmd_log_reflog(argc
, argv
, prefix
, the_repository
);
157 static int show_reflog(const char *refname
, void *cb_data UNUSED
)
159 printf("%s\n", refname
);
163 static int cmd_reflog_list(int argc
, const char **argv
, const char *prefix
,
164 struct repository
*repo UNUSED
)
166 struct option options
[] = {
169 struct ref_store
*ref_store
;
171 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_list_usage
, 0);
173 return error(_("%s does not accept arguments: '%s'"),
176 ref_store
= get_main_ref_store(the_repository
);
178 return refs_for_each_reflog(ref_store
, show_reflog
, NULL
);
181 static int cmd_reflog_expire(int argc
, const char **argv
, const char *prefix
,
182 struct repository
*repo UNUSED
)
184 timestamp_t now
= time(NULL
);
185 struct reflog_expire_options opts
= REFLOG_EXPIRE_OPTIONS_INIT(now
);
186 int i
, status
, do_all
, single_worktree
= 0;
187 unsigned int flags
= 0;
189 reflog_expiry_should_prune_fn
*should_prune_fn
= should_expire_reflog_ent
;
190 const struct option options
[] = {
191 OPT_BIT('n', "dry-run", &flags
, N_("do not actually prune any entries"),
192 EXPIRE_REFLOGS_DRY_RUN
),
193 OPT_BIT(0, "rewrite", &flags
,
194 N_("rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"),
195 EXPIRE_REFLOGS_REWRITE
),
196 OPT_BIT(0, "updateref", &flags
,
197 N_("update the reference to the value of the top reflog entry"),
198 EXPIRE_REFLOGS_UPDATE_REF
),
199 OPT_BOOL(0, "verbose", &verbose
, N_("print extra information on screen")),
200 OPT_CALLBACK_F(0, "expire", &opts
, N_("timestamp"),
201 N_("prune entries older than the specified time"),
203 expire_total_callback
),
204 OPT_CALLBACK_F(0, "expire-unreachable", &opts
, N_("timestamp"),
205 N_("prune entries older than <time> that are not reachable from the current tip of the branch"),
207 expire_unreachable_callback
),
208 OPT_BOOL(0, "stale-fix", &opts
.stalefix
,
209 N_("prune any reflog entries that point to broken commits")),
210 OPT_BOOL(0, "all", &do_all
, N_("process the reflogs of all references")),
211 OPT_BOOL(0, "single-worktree", &single_worktree
,
212 N_("limits processing to reflogs from the current worktree only")),
216 repo_config(the_repository
, reflog_expire_config
, &opts
);
218 save_commit_buffer
= 0;
221 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_expire_usage
, 0);
224 should_prune_fn
= should_expire_reflog_ent_verbose
;
227 * We can trust the commits and objects reachable from refs
228 * even in older repository. We cannot trust what's reachable
229 * from reflog if the repository was pruned with older git.
232 struct rev_info revs
;
234 repo_init_revisions(the_repository
, &revs
, prefix
);
235 revs
.do_not_die_on_missing_objects
= 1;
236 revs
.ignore_missing
= 1;
237 revs
.ignore_missing_links
= 1;
239 printf(_("Marking reachable objects..."));
240 mark_reachable_objects(&revs
, 0, 0, NULL
);
241 release_revisions(&revs
);
247 struct worktree_reflogs collected
= {
248 .reflogs
= STRING_LIST_INIT_DUP
,
250 struct string_list_item
*item
;
251 struct worktree
**worktrees
, **p
;
253 worktrees
= get_worktrees();
254 for (p
= worktrees
; *p
; p
++) {
255 if (single_worktree
&& !(*p
)->is_current
)
257 collected
.worktree
= *p
;
258 refs_for_each_reflog(get_worktree_ref_store(*p
),
259 collect_reflog
, &collected
);
261 free_worktrees(worktrees
);
263 for_each_string_list_item(item
, &collected
.reflogs
) {
264 struct expire_reflog_policy_cb cb
= {
266 .dry_run
= !!(flags
& EXPIRE_REFLOGS_DRY_RUN
),
269 reflog_expire_options_set_refname(&cb
.opts
, item
->string
);
270 status
|= refs_reflog_expire(get_main_ref_store(the_repository
),
272 reflog_expiry_prepare
,
274 reflog_expiry_cleanup
,
277 string_list_clear(&collected
.reflogs
, 0);
280 for (i
= 0; i
< argc
; i
++) {
282 struct expire_reflog_policy_cb cb
= { .opts
= opts
};
284 if (!repo_dwim_log(the_repository
, argv
[i
], strlen(argv
[i
]), NULL
, &ref
)) {
285 status
|= error(_("reflog could not be found: '%s'"), argv
[i
]);
288 reflog_expire_options_set_refname(&cb
.opts
, ref
);
289 status
|= refs_reflog_expire(get_main_ref_store(the_repository
),
291 reflog_expiry_prepare
,
293 reflog_expiry_cleanup
,
298 reflog_clear_expire_config(&opts
);
303 static int cmd_reflog_delete(int argc
, const char **argv
, const char *prefix
,
304 struct repository
*repo UNUSED
)
307 unsigned int flags
= 0;
310 const struct option options
[] = {
311 OPT_BIT('n', "dry-run", &flags
, N_("do not actually prune any entries"),
312 EXPIRE_REFLOGS_DRY_RUN
),
313 OPT_BIT(0, "rewrite", &flags
,
314 N_("rewrite the old SHA1 with the new SHA1 of the entry that now precedes it"),
315 EXPIRE_REFLOGS_REWRITE
),
316 OPT_BIT(0, "updateref", &flags
,
317 N_("update the reference to the value of the top reflog entry"),
318 EXPIRE_REFLOGS_UPDATE_REF
),
319 OPT_BOOL(0, "verbose", &verbose
, N_("print extra information on screen")),
323 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_delete_usage
, 0);
326 return error(_("no reflog specified to delete"));
328 for (i
= 0; i
< argc
; i
++)
329 status
|= reflog_delete(argv
[i
], flags
, verbose
);
334 static int cmd_reflog_exists(int argc
, const char **argv
, const char *prefix
,
335 struct repository
*repo UNUSED
)
337 struct option options
[] = {
342 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_exists_usage
,
345 usage_with_options(reflog_exists_usage
, options
);
348 if (check_refname_format(refname
, REFNAME_ALLOW_ONELEVEL
))
349 die(_("invalid ref format: %s"), refname
);
350 return !refs_reflog_exists(get_main_ref_store(the_repository
),
354 static int cmd_reflog_drop(int argc
, const char **argv
, const char *prefix
,
355 struct repository
*repo
)
357 int ret
= 0, do_all
= 0, single_worktree
= 0;
358 const struct option options
[] = {
359 OPT_BOOL(0, "all", &do_all
, N_("drop the reflogs of all references")),
360 OPT_BOOL(0, "single-worktree", &single_worktree
,
361 N_("drop reflogs from the current worktree only")),
365 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_drop_usage
, 0);
368 usage(_("references specified along with --all"));
371 struct worktree_reflogs collected
= {
372 .reflogs
= STRING_LIST_INIT_DUP
,
374 struct string_list_item
*item
;
375 struct worktree
**worktrees
, **p
;
377 worktrees
= get_worktrees();
378 for (p
= worktrees
; *p
; p
++) {
379 if (single_worktree
&& !(*p
)->is_current
)
381 collected
.worktree
= *p
;
382 refs_for_each_reflog(get_worktree_ref_store(*p
),
383 collect_reflog
, &collected
);
385 free_worktrees(worktrees
);
387 for_each_string_list_item(item
, &collected
.reflogs
)
388 ret
|= refs_delete_reflog(get_main_ref_store(repo
),
390 string_list_clear(&collected
.reflogs
, 0);
395 for (int i
= 0; i
< argc
; i
++) {
397 if (!repo_dwim_log(repo
, argv
[i
], strlen(argv
[i
]), NULL
, &ref
)) {
398 ret
|= error(_("reflog could not be found: '%s'"), argv
[i
]);
402 ret
|= refs_delete_reflog(get_main_ref_store(repo
), ref
);
409 static int cmd_reflog_write(int argc
, const char **argv
, const char *prefix
,
410 struct repository
*repo
)
412 const struct option options
[] = {
415 struct object_id old_oid
, new_oid
;
416 struct strbuf err
= STRBUF_INIT
;
417 struct ref_transaction
*tx
;
418 const char *ref
, *message
;
421 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_write_usage
, 0);
423 usage_with_options(reflog_write_usage
, options
);
426 if (!is_root_ref(ref
) && check_refname_format(ref
, 0))
427 die(_("invalid reference name: %s"), ref
);
429 ret
= get_oid_hex_algop(argv
[1], &old_oid
, repo
->hash_algo
);
431 die(_("invalid old object ID: '%s'"), argv
[1]);
432 if (!is_null_oid(&old_oid
) && !odb_has_object(repo
->objects
, &old_oid
, 0))
433 die(_("old object '%s' does not exist"), argv
[1]);
435 ret
= get_oid_hex_algop(argv
[2], &new_oid
, repo
->hash_algo
);
437 die(_("invalid new object ID: '%s'"), argv
[2]);
438 if (!is_null_oid(&new_oid
) && !odb_has_object(repo
->objects
, &new_oid
, 0))
439 die(_("new object '%s' does not exist"), argv
[2]);
443 tx
= ref_store_transaction_begin(get_main_ref_store(repo
), 0, &err
);
445 die(_("cannot start transaction: %s"), err
.buf
);
447 ret
= ref_transaction_update_reflog(tx
, ref
, &new_oid
, &old_oid
,
448 git_committer_info(0),
451 die(_("cannot queue reflog update: %s"), err
.buf
);
453 ret
= ref_transaction_commit(tx
, &err
);
455 die(_("cannot commit reflog update: %s"), err
.buf
);
457 ref_transaction_free(tx
);
458 strbuf_release(&err
);
465 int cmd_reflog(int argc
,
468 struct repository
*repository
)
470 parse_opt_subcommand_fn
*fn
= NULL
;
471 struct option options
[] = {
472 OPT_SUBCOMMAND("show", &fn
, cmd_reflog_show
),
473 OPT_SUBCOMMAND("list", &fn
, cmd_reflog_list
),
474 OPT_SUBCOMMAND("exists", &fn
, cmd_reflog_exists
),
475 OPT_SUBCOMMAND("write", &fn
, cmd_reflog_write
),
476 OPT_SUBCOMMAND("delete", &fn
, cmd_reflog_delete
),
477 OPT_SUBCOMMAND("drop", &fn
, cmd_reflog_drop
),
478 OPT_SUBCOMMAND("expire", &fn
, cmd_reflog_expire
),
482 argc
= parse_options(argc
, argv
, prefix
, options
, reflog_usage
,
483 PARSE_OPT_SUBCOMMAND_OPTIONAL
|
484 PARSE_OPT_KEEP_DASHDASH
| PARSE_OPT_KEEP_ARGV0
|
485 PARSE_OPT_KEEP_UNKNOWN_OPT
);
487 return fn(argc
- 1, argv
+ 1, prefix
, repository
);
489 return cmd_log_reflog(argc
, argv
, prefix
, repository
);