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
@@ -287,11 +284,29 @@ static int setup_revwalk(struct repository *repo,
287284 return ret ;
288285}
289286
287+ static int handle_ref_update (struct ref_transaction * transaction ,
288+ const char * refname ,
289+ const struct object_id * new_oid ,
290+ const struct object_id * old_oid ,
291+ const char * reflog_msg ,
292+ struct strbuf * err )
293+ {
294+ if (!transaction ) {
295+ printf ("update %s %s %s\n" ,
296+ refname , oid_to_hex (new_oid ), oid_to_hex (old_oid ));
297+ return 0 ;
298+ }
299+
300+ return ref_transaction_update (transaction , refname , new_oid , old_oid ,
301+ NULL , NULL , 0 , reflog_msg , err );
302+ }
303+
290304static int handle_reference_updates (struct rev_info * revs ,
291305 enum ref_action action ,
292306 struct commit * original ,
293307 struct commit * rewritten ,
294- const char * reflog_msg )
308+ const char * reflog_msg ,
309+ int dry_run )
295310{
296311 const struct name_decoration * decoration ;
297312 struct replay_revisions_options opts = { 0 };
@@ -313,82 +328,72 @@ static int handle_reference_updates(struct rev_info *revs,
313328 if (ret )
314329 goto out ;
315330
316- switch (action ) {
317- case REF_ACTION_BRANCHES :
318- case REF_ACTION_HEAD :
331+ if (action != REF_ACTION_BRANCHES && action != REF_ACTION_HEAD )
332+ BUG ("unsupported ref action %d" , action );
333+
334+ if (!dry_run ) {
319335 transaction = ref_store_transaction_begin (get_main_ref_store (revs -> repo ), 0 , & err );
320336 if (!transaction ) {
321337 ret = error (_ ("failed to begin ref transaction: %s" ), err .buf );
322338 goto out ;
323339 }
340+ }
324341
325- for (size_t i = 0 ; i < result .updates_nr ; i ++ ) {
326- ret = ref_transaction_update (transaction ,
327- result .updates [i ].refname ,
328- & result .updates [i ].new_oid ,
329- & result .updates [i ].old_oid ,
330- NULL , NULL , 0 , reflog_msg , & err );
331- if (ret ) {
332- ret = error (_ ("failed to update ref '%s': %s" ),
333- result .updates [i ].refname , err .buf );
334- goto out ;
335- }
342+ for (size_t i = 0 ; i < result .updates_nr ; i ++ ) {
343+ ret = handle_ref_update (transaction ,
344+ result .updates [i ].refname ,
345+ & result .updates [i ].new_oid ,
346+ & result .updates [i ].old_oid ,
347+ reflog_msg , & err );
348+ if (ret ) {
349+ ret = error (_ ("failed to update ref '%s': %s" ),
350+ result .updates [i ].refname , err .buf );
351+ goto out ;
336352 }
353+ }
354+
355+ /*
356+ * `replay_revisions()` only updates references that are
357+ * ancestors of `rewritten`, so we need to manually
358+ * handle updating references that point to `original`.
359+ */
360+ for (decoration = get_name_decoration (& original -> object );
361+ decoration ;
362+ decoration = decoration -> next )
363+ {
364+ if (decoration -> type != DECORATION_REF_LOCAL &&
365+ decoration -> type != DECORATION_REF_HEAD )
366+ continue ;
367+
368+ if (action == REF_ACTION_HEAD &&
369+ decoration -> type != DECORATION_REF_HEAD )
370+ continue ;
337371
338372 /*
339- * `replay_revisions()` only updates references that are
340- * ancestors of `rewritten`, so we need to manually
341- * handle updating references that point to `original` .
373+ * We only need to update HEAD separately in case it's
374+ * detached. If it's not we'd already update the branch
375+ * it is pointing to .
342376 */
343- for (decoration = get_name_decoration (& original -> object );
344- decoration ;
345- decoration = decoration -> next )
346- {
347- if (decoration -> type != DECORATION_REF_LOCAL &&
348- decoration -> type != DECORATION_REF_HEAD )
349- continue ;
350-
351- if (action == REF_ACTION_HEAD &&
352- decoration -> type != DECORATION_REF_HEAD )
353- continue ;
354-
355- /*
356- * We only need to update HEAD separately in case it's
357- * detached. If it's not we'd already update the branch
358- * it is pointing to.
359- */
360- if (action == REF_ACTION_BRANCHES &&
361- decoration -> type == DECORATION_REF_HEAD &&
362- !detached_head )
363- continue ;
364-
365- ret = ref_transaction_update (transaction ,
366- decoration -> name ,
367- & rewritten -> object .oid ,
368- & original -> object .oid ,
369- NULL , NULL , 0 , reflog_msg , & err );
370- if (ret ) {
371- ret = error (_ ("failed to update ref '%s': %s" ),
372- decoration -> name , err .buf );
373- goto out ;
374- }
375- }
376-
377- if (ref_transaction_commit (transaction , & err )) {
378- ret = error (_ ("failed to commit ref transaction: %s" ), err .buf );
377+ if (action == REF_ACTION_BRANCHES &&
378+ decoration -> type == DECORATION_REF_HEAD &&
379+ !detached_head )
380+ continue ;
381+
382+ ret = handle_ref_update (transaction ,
383+ decoration -> name ,
384+ & rewritten -> object .oid ,
385+ & original -> object .oid ,
386+ reflog_msg , & err );
387+ if (ret ) {
388+ ret = error (_ ("failed to update ref '%s': %s" ),
389+ decoration -> name , err .buf );
379390 goto out ;
380391 }
392+ }
381393
382- break ;
383- case REF_ACTION_PRINT :
384- for (size_t i = 0 ; i < result .updates_nr ; i ++ )
385- printf ("update %s %s %s\n" ,
386- result .updates [i ].refname ,
387- oid_to_hex (& result .updates [i ].new_oid ),
388- oid_to_hex (& result .updates [i ].old_oid ));
389- break ;
390- default :
391- BUG ("unsupported ref action %d" , action );
394+ if (transaction && ref_transaction_commit (transaction , & err )) {
395+ ret = error (_ ("failed to commit ref transaction: %s" ), err .buf );
396+ goto out ;
392397 }
393398
394399 ret = 0 ;
@@ -410,10 +415,13 @@ static int cmd_history_reword(int argc,
410415 NULL ,
411416 };
412417 enum ref_action action = REF_ACTION_DEFAULT ;
418+ int dry_run = 0 ;
413419 struct option options [] = {
414420 OPT_CALLBACK_F (0 , "ref-action" , & action , N_ ("<action>" ),
415- N_ ("control ref update behavior (branches|head|print )" ),
421+ N_ ("control ref update behavior (branches|head)" ),
416422 PARSE_OPT_NONEG , parse_ref_action ),
423+ OPT_BOOL ('n' , "dry-run" , & dry_run ,
424+ N_ ("perform a dry-run without updating any refs" )),
417425 OPT_END (),
418426 };
419427 struct strbuf reflog_msg = STRBUF_INIT ;
@@ -450,7 +458,7 @@ static int cmd_history_reword(int argc,
450458 strbuf_addf (& reflog_msg , "reword: updating %s" , argv [0 ]);
451459
452460 ret = handle_reference_updates (& revs , action , original , rewritten ,
453- reflog_msg .buf );
461+ reflog_msg .buf , dry_run );
454462 if (ret < 0 ) {
455463 ret = error (_ ("failed replaying descendants" ));
456464 goto out ;
0 commit comments