1818#include "wt-status.h"
1919
2020#define GIT_HISTORY_REWORD_USAGE \
21- N_("git history reword <commit> [--ref-action=(branches|head|print )]")
21+ N_("git history reword <commit> [--dry-run] [-- ref-action=(branches|head)]")
2222
2323static void change_data_free (void * util , const char * str UNUSED )
2424{
@@ -155,7 +155,6 @@ enum ref_action {
155155 REF_ACTION_DEFAULT ,
156156 REF_ACTION_BRANCHES ,
157157 REF_ACTION_HEAD ,
158- REF_ACTION_PRINT ,
159158};
160159
161160static int parse_ref_action (const struct option * opt , const char * value , int unset )
@@ -167,10 +166,8 @@ static int parse_ref_action(const struct option *opt, const char *value, int uns
167166 * action = REF_ACTION_BRANCHES ;
168167 } else if (!strcmp (value , "head" )) {
169168 * action = REF_ACTION_HEAD ;
170- } else if (!strcmp (value , "print" )) {
171- * action = REF_ACTION_PRINT ;
172169 } else {
173- return error (_ ("%s expects one of 'branches', 'head' or 'print '" ),
170+ return error (_ ("%s expects one of 'branches' or 'head '" ),
174171 opt -> long_name );
175172 }
176173
@@ -286,11 +283,29 @@ static int setup_revwalk(struct repository *repo,
286283 return ret ;
287284}
288285
286+ static int handle_ref_update (struct ref_transaction * transaction ,
287+ const char * refname ,
288+ const struct object_id * new_oid ,
289+ const struct object_id * old_oid ,
290+ const char * reflog_msg ,
291+ struct strbuf * err )
292+ {
293+ if (!transaction ) {
294+ printf ("update %s %s %s\n" ,
295+ refname , oid_to_hex (new_oid ), oid_to_hex (old_oid ));
296+ return 0 ;
297+ }
298+
299+ return ref_transaction_update (transaction , refname , new_oid , old_oid ,
300+ NULL , NULL , 0 , reflog_msg , err );
301+ }
302+
289303static int handle_reference_updates (struct rev_info * revs ,
290304 enum ref_action action ,
291305 struct commit * original ,
292306 struct commit * rewritten ,
293- const char * reflog_msg )
307+ const char * reflog_msg ,
308+ int dry_run )
294309{
295310 const struct name_decoration * decoration ;
296311 struct replay_revisions_options opts = { 0 };
@@ -312,82 +327,72 @@ static int handle_reference_updates(struct rev_info *revs,
312327 if (ret )
313328 goto out ;
314329
315- switch (action ) {
316- case REF_ACTION_BRANCHES :
317- case REF_ACTION_HEAD :
330+ if (action != REF_ACTION_BRANCHES && action != REF_ACTION_HEAD )
331+ BUG ("unsupported ref action %d" , action );
332+
333+ if (!dry_run ) {
318334 transaction = ref_store_transaction_begin (get_main_ref_store (revs -> repo ), 0 , & err );
319335 if (!transaction ) {
320336 ret = error (_ ("failed to begin ref transaction: %s" ), err .buf );
321337 goto out ;
322338 }
339+ }
323340
324- for (size_t i = 0 ; i < result .updates_nr ; i ++ ) {
325- ret = ref_transaction_update (transaction ,
326- result .updates [i ].refname ,
327- & result .updates [i ].new_oid ,
328- & result .updates [i ].old_oid ,
329- NULL , NULL , 0 , reflog_msg , & err );
330- if (ret ) {
331- ret = error (_ ("failed to update ref '%s': %s" ),
332- result .updates [i ].refname , err .buf );
333- goto out ;
334- }
341+ for (size_t i = 0 ; i < result .updates_nr ; i ++ ) {
342+ ret = handle_ref_update (transaction ,
343+ result .updates [i ].refname ,
344+ & result .updates [i ].new_oid ,
345+ & result .updates [i ].old_oid ,
346+ reflog_msg , & err );
347+ if (ret ) {
348+ ret = error (_ ("failed to update ref '%s': %s" ),
349+ result .updates [i ].refname , err .buf );
350+ goto out ;
335351 }
352+ }
353+
354+ /*
355+ * `replay_revisions()` only updates references that are
356+ * ancestors of `rewritten`, so we need to manually
357+ * handle updating references that point to `original`.
358+ */
359+ for (decoration = get_name_decoration (& original -> object );
360+ decoration ;
361+ decoration = decoration -> next )
362+ {
363+ if (decoration -> type != DECORATION_REF_LOCAL &&
364+ decoration -> type != DECORATION_REF_HEAD )
365+ continue ;
366+
367+ if (action == REF_ACTION_HEAD &&
368+ decoration -> type != DECORATION_REF_HEAD )
369+ continue ;
336370
337371 /*
338- * `replay_revisions()` only updates references that are
339- * ancestors of `rewritten`, so we need to manually
340- * handle updating references that point to `original` .
372+ * We only need to update HEAD separately in case it's
373+ * detached. If it's not we'd already update the branch
374+ * it is pointing to .
341375 */
342- for (decoration = get_name_decoration (& original -> object );
343- decoration ;
344- decoration = decoration -> next )
345- {
346- if (decoration -> type != DECORATION_REF_LOCAL &&
347- decoration -> type != DECORATION_REF_HEAD )
348- continue ;
349-
350- if (action == REF_ACTION_HEAD &&
351- decoration -> type != DECORATION_REF_HEAD )
352- continue ;
353-
354- /*
355- * We only need to update HEAD separately in case it's
356- * detached. If it's not we'd already update the branch
357- * it is pointing to.
358- */
359- if (action == REF_ACTION_BRANCHES &&
360- decoration -> type == DECORATION_REF_HEAD &&
361- !detached_head )
362- continue ;
363-
364- ret = ref_transaction_update (transaction ,
365- decoration -> name ,
366- & rewritten -> object .oid ,
367- & original -> object .oid ,
368- NULL , NULL , 0 , reflog_msg , & err );
369- if (ret ) {
370- ret = error (_ ("failed to update ref '%s': %s" ),
371- decoration -> name , err .buf );
372- goto out ;
373- }
374- }
375-
376- if (ref_transaction_commit (transaction , & err )) {
377- ret = error (_ ("failed to commit ref transaction: %s" ), err .buf );
376+ if (action == REF_ACTION_BRANCHES &&
377+ decoration -> type == DECORATION_REF_HEAD &&
378+ !detached_head )
379+ continue ;
380+
381+ ret = handle_ref_update (transaction ,
382+ decoration -> name ,
383+ & rewritten -> object .oid ,
384+ & original -> object .oid ,
385+ reflog_msg , & err );
386+ if (ret ) {
387+ ret = error (_ ("failed to update ref '%s': %s" ),
388+ decoration -> name , err .buf );
378389 goto out ;
379390 }
391+ }
380392
381- break ;
382- case REF_ACTION_PRINT :
383- for (size_t i = 0 ; i < result .updates_nr ; i ++ )
384- printf ("update %s %s %s\n" ,
385- result .updates [i ].refname ,
386- oid_to_hex (& result .updates [i ].new_oid ),
387- oid_to_hex (& result .updates [i ].old_oid ));
388- break ;
389- default :
390- BUG ("unsupported ref action %d" , action );
393+ if (transaction && ref_transaction_commit (transaction , & err )) {
394+ ret = error (_ ("failed to commit ref transaction: %s" ), err .buf );
395+ goto out ;
391396 }
392397
393398 ret = 0 ;
@@ -409,10 +414,13 @@ static int cmd_history_reword(int argc,
409414 NULL ,
410415 };
411416 enum ref_action action = REF_ACTION_DEFAULT ;
417+ int dry_run = 0 ;
412418 struct option options [] = {
413419 OPT_CALLBACK_F (0 , "ref-action" , & action , N_ ("<action>" ),
414- N_ ("control ref update behavior (branches|head|print )" ),
420+ N_ ("control ref update behavior (branches|head)" ),
415421 PARSE_OPT_NONEG , parse_ref_action ),
422+ OPT_BOOL ('n' , "dry-run" , & dry_run ,
423+ N_ ("perform a dry-run without updating any refs" )),
416424 OPT_END (),
417425 };
418426 struct strbuf reflog_msg = STRBUF_INIT ;
@@ -449,7 +457,7 @@ static int cmd_history_reword(int argc,
449457 strbuf_addf (& reflog_msg , "reword: updating %s" , argv [0 ]);
450458
451459 ret = handle_reference_updates (& revs , action , original , rewritten ,
452- reflog_msg .buf );
460+ reflog_msg .buf , dry_run );
453461 if (ret < 0 ) {
454462 ret = error (_ ("failed replaying descendants" ));
455463 goto out ;
0 commit comments