Commit Diff


commit - 3f670bfb38a502b7309f7db354b9d4f767ea12fc
commit + 466785b9264da1a24c92aed9d706e76cc826601d
blob - c44524c54ba55850265ed0fc7be1f083914d1309
blob + f8e70b868b5d03985616d549fb6447025772eef9
--- got/got.1
+++ got/got.1
@@ -1489,7 +1489,7 @@ If this option is used, no other command-line argument
 .It Cm rb
 Short alias for
 .Cm rebase .
-.It Cm histedit Oo Fl a Oc Oo Fl c Oc Oo Fl F Ar histedit-script Oc Oo Fl m Oc
+.It Cm histedit Oo Fl a Oc Oo Fl c Oc Oo Fl f Oc Oo Fl F Ar histedit-script Oc Oo Fl m Oc
 Edit commit history between the work tree's current base commit and
 the tip commit of the work tree's current branch.
 .Pp
@@ -1517,8 +1517,15 @@ Editing of commit history is controlled via a
 .Ar histedit script
 which can be written in an editor based on a template, passed on the
 command line, or generated with the
+.Fl f
+or
 .Fl m
-option if only log messages need to be edited.
+options.
+The
+.Fl f
+option folds all commits into one commit, while the
+.Fl m
+option is used only if log messages need to be edited.
 .Pp
 The format of the histedit script is line-based.
 Each line in the script begins with a command name, followed by
@@ -1618,6 +1625,11 @@ If this option is used, no other command-line argument
 .It Fl c
 Continue an interrupted histedit operation.
 If this option is used, no other command-line arguments are allowed.
+.It Fl f
+Fold all commits into a single commit.
+This option is a quick equivalent to a histedit script which folds all
+commits, combining them all into one commit.
+If this option is used, no other command-line arguments are allowed.
 .It Fl F Ar histedit-script
 Use the specified
 .Ar histedit-script
blob - 3b8ba655c02b9df7b4088a73f765a46b9f598e97
blob + 7bdd9e142a5f26254c73c308684bb6d6da95ef20
--- got/got.c
+++ got/got.c
@@ -7747,7 +7747,7 @@ done:
 __dead static void
 usage_histedit(void)
 {
-	fprintf(stderr, "usage: %s histedit [-a] [-c] [-F histedit-script] [-m]\n",
+	fprintf(stderr, "usage: %s histedit [-a] [-c] [-f] [-F histedit-script] [-m]\n",
 	    getprogname());
 	exit(1);
 }
@@ -7814,17 +7814,20 @@ done:
 
 static const struct got_error *
 histedit_write_commit_list(struct got_object_id_queue *commits,
-    FILE *f, int edit_logmsg_only, struct got_repository *repo)
+    FILE *f, int edit_logmsg_only, int fold_only, struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
 	struct got_object_qid *qid;
+	const char *histedit_cmd = NULL;
 
 	if (SIMPLEQ_EMPTY(commits))
 		return got_error(GOT_ERR_EMPTY_HISTEDIT);
 
 	SIMPLEQ_FOREACH(qid, commits, entry) {
-		err = histedit_write_commit(qid->id, got_histedit_cmds[0].name,
-		    f, repo);
+		histedit_cmd = got_histedit_cmds[0].name;
+		if (fold_only && SIMPLEQ_NEXT(qid, entry) != NULL)
+			histedit_cmd = "fold";
+		err = histedit_write_commit(qid->id, histedit_cmd, f, repo);
 		if (err)
 			break;
 		if (edit_logmsg_only) {
@@ -8232,7 +8235,7 @@ histedit_edit_list_retry(struct got_histedit_list *, c
 static const struct got_error *
 histedit_edit_script(struct got_histedit_list *histedit_cmds,
     struct got_object_id_queue *commits, const char *branch_name,
-    int edit_logmsg_only, struct got_repository *repo)
+    int edit_logmsg_only, int fold_only, struct got_repository *repo)
 {
 	const struct got_error *err;
 	FILE *f = NULL;
@@ -8246,11 +8249,12 @@ histedit_edit_script(struct got_histedit_list *histedi
 	if (err)
 		goto done;
 
-	err = histedit_write_commit_list(commits, f, edit_logmsg_only, repo);
+	err = histedit_write_commit_list(commits, f, edit_logmsg_only,
+	    fold_only, repo);
 	if (err)
 		goto done;
 
-	if (edit_logmsg_only) {
+	if (edit_logmsg_only || fold_only) {
 		rewind(f);
 		err = histedit_parse_list(histedit_cmds, f, repo);
 	} else {
@@ -8381,7 +8385,7 @@ histedit_edit_list_retry(struct got_histedit_list *his
 		} else if (resp == 'r') {
 			histedit_free_list(histedit_cmds);
 			err = histedit_edit_script(histedit_cmds,
-			    commits, branch_name, 0, repo);
+			    commits, branch_name, 0, 0, repo);
 			if (err) {
 				if (err->code != GOT_ERR_HISTEDIT_SYNTAX &&
 				    err->code != GOT_ERR_HISTEDIT_CMD)
@@ -8573,7 +8577,7 @@ cmd_histedit(int argc, char *argv[])
 	int ch, rebase_in_progress = 0;
 	struct got_update_progress_arg upa;
 	int edit_in_progress = 0, abort_edit = 0, continue_edit = 0;
-	int edit_logmsg_only = 0;
+	int edit_logmsg_only = 0, fold_only = 0;
 	const char *edit_script_path = NULL;
 	unsigned char rebase_status = GOT_STATUS_NO_CHANGE;
 	struct got_object_id_queue commits;
@@ -8588,7 +8592,7 @@ cmd_histedit(int argc, char *argv[])
 	TAILQ_INIT(&merged_paths);
 	memset(&upa, 0, sizeof(upa));
 
-	while ((ch = getopt(argc, argv, "acF:m")) != -1) {
+	while ((ch = getopt(argc, argv, "acfF:m")) != -1) {
 		switch (ch) {
 		case 'a':
 			abort_edit = 1;
@@ -8596,6 +8600,9 @@ cmd_histedit(int argc, char *argv[])
 		case 'c':
 			continue_edit = 1;
 			break;
+		case 'f':
+			fold_only = 1;
+			break;
 		case 'F':
 			edit_script_path = optarg;
 			break;
@@ -8624,6 +8631,12 @@ cmd_histedit(int argc, char *argv[])
 		errx(1, "histedit's -a and -m options are mutually exclusive");
 	if (continue_edit && edit_logmsg_only)
 		errx(1, "histedit's -c and -m options are mutually exclusive");
+	if (abort_edit && fold_only)
+		errx(1, "histedit's -a and -f options are mutually exclusive");
+	if (continue_edit && fold_only)
+		errx(1, "histedit's -c and -f options are mutually exclusive");
+	if (fold_only && edit_logmsg_only)
+		errx(1, "histedit's -f and -m options are mutually exclusive");
 	if (argc != 0)
 		usage_histedit();
 
@@ -8672,6 +8685,13 @@ cmd_histedit(int argc, char *argv[])
 		    "before the -m option can be used");
 		goto done;
 	}
+	if (edit_in_progress && fold_only) {
+		error = got_error_msg(GOT_ERR_HISTEDIT_BUSY,
+		    "histedit operation is in progress in this "
+		    "work tree and must be continued or aborted "
+		    "before the -f option can be used");
+		goto done;
+	}
 
 	if (edit_in_progress && abort_edit) {
 		error = got_worktree_histedit_continue(&resume_commit_id,
@@ -8807,7 +8827,7 @@ cmd_histedit(int argc, char *argv[])
 			if (strncmp(branch_name, "refs/heads/", 11) == 0)
 				branch_name += 11;
 			error = histedit_edit_script(&histedit_cmds, &commits,
-			    branch_name, edit_logmsg_only, repo);
+			    branch_name, edit_logmsg_only, fold_only, repo);
 			if (error) {
 				got_worktree_histedit_abort(worktree, fileindex,
 				    repo, branch, base_commit_id,