git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: "Viaceslavus via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Viaceslavus <vaceslavkozin619@gmail.com>,
	Viacelaus <vaceslavkozin619@gmail.com>
Subject: [PATCH] forbid a hard reset before the initial commit
Date: Wed, 02 Feb 2022 11:52:01 +0000	[thread overview]
Message-ID: <pull.1137.git.1643802721612.gitgitgadget@gmail.com> (raw)

From: Viacelaus <vaceslavkozin619@gmail.com>

Performing 'git reset --hard' on empty repo with staged files
may have the only one possible result - deleting all staged files.
Such behaviour may be unexpected or even dangerous. With this
commit, when running 'git reset --hard', git will check for the
existence of commits in the repo; in case of absence of such, and
also if there are any files staged, git will die with an error.

Signed-off-by: Viacelaus <vaceslavkozin619@gmail.com>
---
    Forbid a hard reset on empty repo with staged files.
    
    Performing git reset --hard on empty repo (initialized repository
    without any commits) with staged files may have the only one possible
    result - deleting all staged files. Such behaviour may be unexpected or
    even dangerous, as it is possible to permanently delete the whole
    project. It is also absolutely useless. So with this patch, when running
    git reset --hard, git will check for the existence of commits in the
    repository; in case of absence of such, and also if there are files
    staged, git will return an error. All the tests were added into
    t/t7104-reset-hard.sh file.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1137%2FViaceslavus%2Fhard-reset-safety-on-empty-repo-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1137/Viaceslavus/hard-reset-safety-on-empty-repo-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1137

 builtin/reset.c                | 14 ++++++++++++++
 t/t7104-reset-hard.sh          | 18 ++++++++++++++++++
 t/t7106-reset-unborn-branch.sh | 11 -----------
 3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/builtin/reset.c b/builtin/reset.c
index b97745ee94e..5a0e80d380f 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -301,6 +301,11 @@ static void die_if_unmerged_cache(int reset_type)
 
 }
 
+static int check_commit_exists(const char *refname, const struct object_id *oid, int f, void *d)
+{
+	return is_branch(refname);
+}
+
 static void parse_args(struct pathspec *pathspec,
 		       const char **argv, const char *prefix,
 		       int patch_mode,
@@ -474,6 +479,15 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 			die(_("Cannot do %s reset with paths."),
 					_(reset_type_names[reset_type]));
 	}
+
+	if (reset_type == HARD) {
+		int commits_exist = for_each_fullref_in("refs/heads", check_commit_exists, NULL);
+		if(!commits_exist) {
+			if(read_cache() == 1)
+				die(_("Hard reset isn`t allowed before the first commit."));
+		}
+	}
+
 	if (reset_type == NONE)
 		reset_type = MIXED; /* by default */
 
diff --git a/t/t7104-reset-hard.sh b/t/t7104-reset-hard.sh
index cf9697eba9a..30fb71e6fb9 100755
--- a/t/t7104-reset-hard.sh
+++ b/t/t7104-reset-hard.sh
@@ -44,4 +44,22 @@ test_expect_success 'reset --hard did not corrupt index or cache-tree' '
 
 '
 
+test_expect_success 'reset --hard on empty repo without staged changes works fine' '
+	git reset --hard
+'
+
+test_expect_success 'reset --hard on empty repo with staged changes results in an error' '
+	touch n &&
+	git add n &&
+	test_must_fail git reet --hard
+'
+
+test_expect_success 'reset --hard after a commit works fine' '
+	touch new &&
+	git add new &&
+	git commit -m "initial" &&
+	git reset --hard 2> error &&
+	test_must_be_empty error
+'
+
 test_done
diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh
index ecb85c3b823..8d45f640480 100755
--- a/t/t7106-reset-unborn-branch.sh
+++ b/t/t7106-reset-unborn-branch.sh
@@ -53,15 +53,4 @@ test_expect_success 'reset --soft is a no-op' '
 	test_cmp expect actual
 '
 
-test_expect_success 'reset --hard' '
-	rm .git/index &&
-	git add a &&
-	test_when_finished "echo a >a" &&
-	git reset --hard &&
-
-	git ls-files >actual &&
-	test_must_be_empty actual &&
-	test_path_is_missing a
-'
-
 test_done

base-commit: 5d01301f2b865aa8dba1654d3f447ce9d21db0b5
-- 
gitgitgadget

             reply	other threads:[~2022-02-02 11:52 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-02 11:52 Viaceslavus via GitGitGadget [this message]
2022-02-02 21:05 ` [PATCH] forbid a hard reset before the initial commit Junio C Hamano
2022-02-11 22:26 ` [PATCH v2] hard reset safe mode Viaceslavus via GitGitGadget
2022-02-11 23:03   ` Junio C Hamano
2022-02-14  3:14     ` Bagas Sanjaya
2022-02-14 11:44       ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=pull.1137.git.1643802721612.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=vaceslavkozin619@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).