1818#include "lockfile.h"
1919#include "parse-options.h"
2020#include "commit.h"
21+ #include "diff.h"
2122
2223static char const * const builtin_rebase_usage [] = {
2324 N_ ("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
@@ -81,6 +82,8 @@ struct rebase_options {
8182 int dont_finish_rebase ;
8283 enum {
8384 REBASE_NO_QUIET = 1 <<0 ,
85+ REBASE_VERBOSE = 1 <<1 ,
86+ REBASE_DIFFSTAT = 1 <<2 ,
8487 } flags ;
8588 struct strbuf git_am_opt ;
8689};
@@ -166,6 +169,10 @@ static int run_specific_rebase(struct rebase_options *opts)
166169 add_var (& script_snippet , "GIT_QUIET" ,
167170 opts -> flags & REBASE_NO_QUIET ? "" : "t" );
168171 add_var (& script_snippet , "git_am_opt" , opts -> git_am_opt .buf );
172+ add_var (& script_snippet , "verbose" ,
173+ opts -> flags & REBASE_VERBOSE ? "t" : "" );
174+ add_var (& script_snippet , "diffstat" ,
175+ opts -> flags & REBASE_DIFFSTAT ? "t" : "" );
169176
170177 switch (opts -> type ) {
171178 case REBASE_AM :
@@ -311,6 +318,21 @@ static int reset_head(struct object_id *oid, const char *action,
311318 return ret ;
312319}
313320
321+ static int rebase_config (const char * var , const char * value , void * data )
322+ {
323+ struct rebase_options * opts = data ;
324+
325+ if (!strcmp (var , "rebase.stat" )) {
326+ if (git_config_bool (var , value ))
327+ opts -> flags |= REBASE_DIFFSTAT ;
328+ else
329+ opts -> flags &= !REBASE_DIFFSTAT ;
330+ return 0 ;
331+ }
332+
333+ return git_default_config (var , value , data );
334+ }
335+
314336int cmd_rebase (int argc , const char * * argv , const char * prefix )
315337{
316338 struct rebase_options options = {
@@ -332,7 +354,13 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
332354 N_ ("allow pre-rebase hook to run" )),
333355 OPT_NEGBIT ('q' , "quiet" , & options .flags ,
334356 N_ ("be quiet. implies --no-stat" ),
335- REBASE_NO_QUIET ),
357+ REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT ),
358+ OPT_BIT ('v' , "verbose" , & options .flags ,
359+ N_ ("display a diffstat of what changed upstream" ),
360+ REBASE_NO_QUIET | REBASE_VERBOSE | REBASE_DIFFSTAT ),
361+ {OPTION_NEGBIT , 'n' , "no-stat" , & options .flags , NULL ,
362+ N_ ("do not show diffstat of what changed upstream" ),
363+ PARSE_OPT_NOARG , NULL , REBASE_DIFFSTAT },
336364 OPT_END (),
337365 };
338366
@@ -360,7 +388,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
360388 trace_repo_setup (prefix );
361389 setup_work_tree ();
362390
363- git_config (git_default_config , NULL );
391+ git_config (rebase_config , & options );
392+
364393 argc = parse_options (argc , argv , prefix ,
365394 builtin_rebase_options ,
366395 builtin_rebase_usage , 0 );
@@ -456,6 +485,33 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
456485 argc ? argv [0 ] : NULL , NULL ))
457486 die (_ ("The pre-rebase hook refused to rebase." ));
458487
488+ if (options .flags & REBASE_DIFFSTAT ) {
489+ struct diff_options opts ;
490+
491+ if (options .flags & REBASE_VERBOSE )
492+ printf (_ ("Changes from %s to %s:\n" ),
493+ oid_to_hex (& merge_base ),
494+ oid_to_hex (& options .onto -> object .oid ));
495+
496+ /* We want color (if set), but no pager */
497+ diff_setup (& opts );
498+ opts .stat_width = -1 ; /* use full terminal width */
499+ opts .stat_graph_width = -1 ; /* respect statGraphWidth config */
500+ opts .output_format |=
501+ DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT ;
502+ opts .detect_rename = DIFF_DETECT_RENAME ;
503+ diff_setup_done (& opts );
504+ diff_tree_oid (& merge_base , & options .onto -> object .oid ,
505+ "" , & opts );
506+ diffcore_std (& opts );
507+ diff_flush (& opts );
508+ }
509+
510+ /* Detach HEAD and reset the tree */
511+ if (options .flags & REBASE_NO_QUIET )
512+ printf (_ ("First, rewinding head to replay your work on top of "
513+ "it...\n" ));
514+
459515 strbuf_addf (& msg , "rebase: checkout %s" , options .onto_name );
460516 if (reset_head (& options .onto -> object .oid , "checkout" , NULL , 1 ))
461517 die (_ ("Could not detach HEAD" ));
0 commit comments