git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] reset --hard: warn before discarding staged content with no commit history
@ 2025-12-10 15:01 Koutsouflakis Stefanos
  2025-12-11  3:24 ` Junio C Hamano
  2025-12-12 22:14 ` D. Ben Knoble
  0 siblings, 2 replies; 13+ messages in thread
From: Koutsouflakis Stefanos @ 2025-12-10 15:01 UTC (permalink / raw)
  To: git@vger.kernel.org

When running "git reset --hard" in a repository where staged content
has never been committed, the staged files are lost. This seems like a case where requiring --force could be helpful.

Reproduction:

    mkdir test && cd test
    git init
    echo "hello" > a.txt
    git add .
    git reset --hard

Result: a.txt is removed from both the index and working tree.
While the blob temporarily remains as a dangling object (recoverable
via "git fsck --lost-found" until garbage collection), this is not a
realistic safety net as the filename is lost and most users are
unaware of this recovery mechanism.

The most likely scenario is a user initializing a Git repository in an
existing project. They have a folder with files they've been working on,
run "git init", then "git add ." to stage everything. A mistyped or
misunderstood command later, their entire project is wiped out.

Proposed behavior:

When "git reset --hard" would discard staged content that does not
exist in any commit (i.e., the blob has no reachable reference),
print a warning and require confirmation or --force:

    warning: the following staged files have never been committed
    and will be permanently lost:
        a.txt
    use --force to proceed, or commit first

This would be consistent with Git's general trend toward safer
defaults.

Questions for discussion:

1. Is this safety check worth the added complexity?

2. Are there workflows where this would be annoying? (can't think of any but I might be missing something).

I'm happy to work on a patch if there's interest.

Thanks,
Stefanos

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-10 15:01 [RFC] reset --hard: warn before discarding staged content with no commit history Koutsouflakis Stefanos
@ 2025-12-11  3:24 ` Junio C Hamano
  2025-12-11  3:59   ` Eric Sunshine
  2025-12-11 11:53   ` Koutsouflakis Stefanos
  2025-12-12 22:14 ` D. Ben Knoble
  1 sibling, 2 replies; 13+ messages in thread
From: Junio C Hamano @ 2025-12-11  3:24 UTC (permalink / raw)
  To: Koutsouflakis Stefanos; +Cc: git@vger.kernel.org

Koutsouflakis Stefanos <koutsouflakis.stefanos@proton.me> writes:

> When running "git reset --hard" in a repository where staged
> content has never been committed, the staged files are lost. This
> seems like a case where requiring --force could be helpful.

The thinking has always been "'--hard' means what it says!  HARD
removes things harder than other modes---there is need to add
'--force' to it".

So, I dunno.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-11  3:24 ` Junio C Hamano
@ 2025-12-11  3:59   ` Eric Sunshine
  2025-12-11  5:25     ` Junio C Hamano
  2025-12-11 11:53   ` Koutsouflakis Stefanos
  1 sibling, 1 reply; 13+ messages in thread
From: Eric Sunshine @ 2025-12-11  3:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Koutsouflakis Stefanos, git@vger.kernel.org

On Wed, Dec 10, 2025 at 10:24 PM Junio C Hamano <gitster@pobox.com> wrote:
> Koutsouflakis Stefanos <koutsouflakis.stefanos@proton.me> writes:
> > When running "git reset --hard" in a repository where staged
> > content has never been committed, the staged files are lost. This
> > seems like a case where requiring --force could be helpful.
>
> The thinking has always been "'--hard' means what it says!  HARD
> removes things harder than other modes---there is need to add
> '--force' to it".

Presumably, you meant "there is *no* need" rather than "there is need".

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-11  3:59   ` Eric Sunshine
@ 2025-12-11  5:25     ` Junio C Hamano
  0 siblings, 0 replies; 13+ messages in thread
From: Junio C Hamano @ 2025-12-11  5:25 UTC (permalink / raw)
  To: Eric Sunshine; +Cc: Koutsouflakis Stefanos, git@vger.kernel.org

Eric Sunshine <sunshine@sunshineco.com> writes:

> On Wed, Dec 10, 2025 at 10:24 PM Junio C Hamano <gitster@pobox.com> wrote:
>> Koutsouflakis Stefanos <koutsouflakis.stefanos@proton.me> writes:
>> > When running "git reset --hard" in a repository where staged
>> > content has never been committed, the staged files are lost. This
>> > seems like a case where requiring --force could be helpful.
>>
>> The thinking has always been "'--hard' means what it says!  HARD
>> removes things harder than other modes---there is need to add
>> '--force' to it".
>
> Presumably, you meant "there is *no* need" rather than "there is need".

Thanks.  I rewrote the paragraph a few times and somehow losing the
crucial negation from there..

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-11  3:24 ` Junio C Hamano
  2025-12-11  3:59   ` Eric Sunshine
@ 2025-12-11 11:53   ` Koutsouflakis Stefanos
  2025-12-11 12:22     ` Johannes Sixt
  1 sibling, 1 reply; 13+ messages in thread
From: Koutsouflakis Stefanos @ 2025-12-11 11:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org

On Wed, Dec 10, 2025 at 10:24 PM Junio C Hamano <gitster@pobox.com> wrote:
> Koutsouflakis Stefanos <koutsouflakis.stefanos@proton.me> writes:
> > When running "git reset --hard" in a repository where staged
> > content has never been committed, the staged files are lost. This
> > seems like a case where requiring --force could be helpful.
>
> The thinking has always been "'--hard' means what it says!  HARD
> removes things harder than other modes---there is need to add
> '--force' to it".

I agree that "--hard" conveys serious intent. But I would argue there is a meaningful difference between "lose your uncommitted changes" and "lose your entire project".

To be clear, I'm addressing a very narrow scenario:
the user has run init on an existing codebase, staged files
with git add, but has not yet made a first commit. Running
reset --hard at this point destroys the entire project
with no realistic recovery path. This is almost certainly
never intentional.

Thanks,
Stefanos



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-11 11:53   ` Koutsouflakis Stefanos
@ 2025-12-11 12:22     ` Johannes Sixt
  2025-12-11 16:33       ` Koutsouflakis Stefanos
  2025-12-12  3:24       ` Junio C Hamano
  0 siblings, 2 replies; 13+ messages in thread
From: Johannes Sixt @ 2025-12-11 12:22 UTC (permalink / raw)
  To: Koutsouflakis Stefanos, Junio C Hamano; +Cc: git@vger.kernel.org

Am 11.12.25 um 12:53 schrieb Koutsouflakis Stefanos:
> On Wed, Dec 10, 2025 at 10:24 PM Junio C Hamano <gitster@pobox.com> wrote:
>> The thinking has always been "'--hard' means what it says!  HARD
>> removes things harder than other modes---there is [no] need to add
>> '--force' to it".
> 
> I agree that "--hard" conveys serious intent. But I would argue
> there is a meaningful difference between "lose your uncommitted
> changes" and "lose your entire project".
> 
> To be clear, I'm addressing a very narrow scenario:
> the user has run init on an existing codebase, staged files
> with git add, but has not yet made a first commit. Running
> reset --hard at this point destroys the entire project
> with no realistic recovery path. This is almost certainly
> never intentional.
I would argue that bad "tutorials" and "recipes" are to blame. I have
seen far too many that casually suggest `git reset --hard` without
warning and in an easy to copy-and-paste format.

Wouldn't the following slightly different scenario warrant a similar
safety net:

   git commit --allow-empty -m "Initial commit"
   git add .
   git reset --hard

That said, I have some sympathy for the case. Would it be palatable to
have `git reset --hard` refuse to do anything if the destination tree is
empty?

-- Hannes


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-11 12:22     ` Johannes Sixt
@ 2025-12-11 16:33       ` Koutsouflakis Stefanos
  2025-12-12  3:24       ` Junio C Hamano
  1 sibling, 0 replies; 13+ messages in thread
From: Koutsouflakis Stefanos @ 2025-12-11 16:33 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Junio C Hamano, git@vger.kernel.org

On Thursday, December 11th, 2025 at 14:34, Johannes Sixt <j6t@kdbg.org> wrote:

> Am 11.12.25 um 12:53 schrieb Koutsouflakis Stefanos:
> 
> > On Wed, Dec 10, 2025 at 10:24 PM Junio C Hamano gitster@pobox.com wrote:
> > 
> > > The thinking has always been "'--hard' means what it says! HARD
> > > removes things harder than other modes---there is [no] need to add
> > > '--force' to it".
> > 
> > I agree that "--hard" conveys serious intent. But I would argue
> > there is a meaningful difference between "lose your uncommitted
> > changes" and "lose your entire project".
> > 
> > To be clear, I'm addressing a very narrow scenario:
> > the user has run init on an existing codebase, staged files
> > with git add, but has not yet made a first commit. Running
> > reset --hard at this point destroys the entire project
> > with no realistic recovery path. This is almost certainly
> > never intentional.
> 
> I would argue that bad "tutorials" and "recipes" are to blame. I have
> seen far too many that casually suggest `git reset --hard` without
> warning and in an easy to copy-and-paste format.

Agreed. Many users copy-paste their way through Git or use commands
they don't fully understand. That's not the ideal way to interact with 
Git, but they don't deserve do be punished.
 
> That said, I have some sympathy for the case. Would it be palatable to
> have `git reset --hard` refuse to do anything if the destination tree is
> empty?
> 
> -- Hannes

Good point. Checking for an empty destination tree seems to be
the better approach. 
Refusing to proceed (without providing the option of bypassing 
it with --force) also seems reasonable, maybe with a helpful 
message explaining the reason. 
On a second thought "--hard --force" is a bit redundant, 
like "rm -rf --really-delete".

Thanks,
Stefanos

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-11 12:22     ` Johannes Sixt
  2025-12-11 16:33       ` Koutsouflakis Stefanos
@ 2025-12-12  3:24       ` Junio C Hamano
  2025-12-14 13:29         ` Koutsouflakis Stefanos
  1 sibling, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2025-12-12  3:24 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Koutsouflakis Stefanos, git@vger.kernel.org

Johannes Sixt <j6t@kdbg.org> writes:

> Wouldn't the following slightly different scenario warrant a similar
> safety net:
>
>    git commit --allow-empty -m "Initial commit"
>    git add .
>    git reset --hard

Yes, I think everybody has lost new files not in an empty tree but
more often (1) create a new file and add it, (2) make modifications
to existing files, (3) compile, test, debug, get frustrated, and
finally (4) decide to give up and start from scratch, with "reset
--hard".  When (1) is much larger than (2), the sense of loss is
big.

> That said, I have some sympathy for the case. Would it be palatable to
> have `git reset --hard` refuse to do anything if the destination tree is
> empty?

I doubt that special casing an empty tree would fly well.

It is tempting to special case removals, but then I sill am not sure
it is good to do nothing and fail the command after determining that
the operation is a common pitfall of removing a new file that
appears nowhere else.  Unconditionally going interactive is a no-no.

And I do not have any better ideas.  Other than just failing, that is.
But that leads to nonsense combination "--hard --force", just as
idiotic combination as "rm -f -i" :-/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-10 15:01 [RFC] reset --hard: warn before discarding staged content with no commit history Koutsouflakis Stefanos
  2025-12-11  3:24 ` Junio C Hamano
@ 2025-12-12 22:14 ` D. Ben Knoble
  1 sibling, 0 replies; 13+ messages in thread
From: D. Ben Knoble @ 2025-12-12 22:14 UTC (permalink / raw)
  To: Koutsouflakis Stefanos; +Cc: git@vger.kernel.org

On Wed, Dec 10, 2025 at 10:04 AM Koutsouflakis Stefanos
<koutsouflakis.stefanos@proton.me> wrote:
>
> When running "git reset --hard" in a repository where staged content
> has never been committed, the staged files are lost. This seems like a case where requiring --force could be helpful.
>
> Reproduction:
>
>     mkdir test && cd test
>     git init
>     echo "hello" > a.txt
>     git add .
>     git reset --hard
>
> Result: a.txt is removed from both the index and working tree.
> While the blob temporarily remains as a dangling object (recoverable
> via "git fsck --lost-found" until garbage collection), this is not a
> realistic safety net as the filename is lost and most users are
> unaware of this recovery mechanism.
>
> The most likely scenario is a user initializing a Git repository in an
> existing project. They have a folder with files they've been working on,
> run "git init", then "git add ." to stage everything. A mistyped or
> misunderstood command later, their entire project is wiped out.
>
> Proposed behavior:
>
> When "git reset --hard" would discard staged content that does not
> exist in any commit (i.e., the blob has no reachable reference),
> print a warning and require confirmation or --force:
>
>     warning: the following staged files have never been committed
>     and will be permanently lost:
>         a.txt
>     use --force to proceed, or commit first
>
> This would be consistent with Git's general trend toward safer
> defaults.
>
> Questions for discussion:
>
> 1. Is this safety check worth the added complexity?
>
> 2. Are there workflows where this would be annoying? (can't think of any but I might be missing something).
>
> I'm happy to work on a patch if there's interest.
>
> Thanks,
> Stefanos
>

Perhaps useful for future readers who are looking for ways to recover
the objects: https://blog.plover.com/prog/git-reset-disaster.html

-- 
D. Ben Knoble

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-12  3:24       ` Junio C Hamano
@ 2025-12-14 13:29         ` Koutsouflakis Stefanos
  2025-12-14 13:45           ` Štefan Balog
  2025-12-14 23:27           ` Junio C Hamano
  0 siblings, 2 replies; 13+ messages in thread
From: Koutsouflakis Stefanos @ 2025-12-14 13:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Sixt, git@vger.kernel.org

On Friday, December 12th, 2025 at 05:25, Junio C Hamano <gitster@pobox.com> wrote:

> I doubt that special casing an empty tree would fly well.

I might be missing something, could you say more about 
what makes this problematic? 
If it is about breaking existing workflows: any script that 
automates either of the two use-cases discussed would be relying 
on behavior that is almost certainly unintended. Such scripts 
would fail, but without data loss, and give authors a clear 
signal to fix a likely bug. 

> And I do not have any better ideas.  Other than just failing, that is.
> But that leads to nonsense combination "--hard --force", just as
> idiotic combination as "rm -f -i" :-/

There might be other ways to mitigate this, e.g.:
a) Refuse with a fatal error and hint the user
   to remove staged content with "git rm --cached -r ."
b) Autostash with a warning 

Thanks,
Stefanos

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-14 13:29         ` Koutsouflakis Stefanos
@ 2025-12-14 13:45           ` Štefan Balog
  2025-12-14 23:27           ` Junio C Hamano
  1 sibling, 0 replies; 13+ messages in thread
From: Štefan Balog @ 2025-12-14 13:45 UTC (permalink / raw)
  To: Koutsouflakis Stefanos; +Cc: Junio C Hamano, Johannes Sixt, git


[-- Attachment #1.1: Type: text/plain, Size: 1328 bytes --]

Dôvera, spolupráca, jednota !
Jedina cesta posunu genetického kódu a vyvoja pre zlepšenie kvality života
ľudí a spoločnosti v ktorej víťazí dokonalá súhra dôvery viery a nádeje v
lepší svet v symbióze s kozmom.

World Rescue Organization

Dňa ne, 14. dec 2025, 14:30 Koutsouflakis Stefanos <
koutsouflakis.stefanos@proton.me> napísal(a):

> On Friday, December 12th, 2025 at 05:25, Junio C Hamano <gitster@pobox.com>
> wrote:
>
> > I doubt that special casing an empty tree would fly well.
>
> I might be missing something, could you say more about
> what makes this problematic?
> If it is about breaking existing workflows: any script that
> automates either of the two use-cases discussed would be relying
> on behavior that is almost certainly unintended. Such scripts
> would fail, but without data loss, and give authors a clear
> signal to fix a likely bug.
>
> > And I do not have any better ideas.  Other than just failing, that is.
> > But that leads to nonsense combination "--hard --force", just as
> > idiotic combination as "rm -f -i" :-/
>
> There might be other ways to mitigate this, e.g.:
> a) Refuse with a fatal error and hint the user
>    to remove staged content with "git rm --cached -r ."
> b) Autostash with a warning
>
> Thanks,
> Stefanos
>
>

[-- Attachment #1.2: Type: text/html, Size: 1882 bytes --]

[-- Attachment #2: 1765443641414.jpg --]
[-- Type: image/jpeg, Size: 2125327 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-14 13:29         ` Koutsouflakis Stefanos
  2025-12-14 13:45           ` Štefan Balog
@ 2025-12-14 23:27           ` Junio C Hamano
  2025-12-15  7:22             ` Koutsouflakis Stefanos
  1 sibling, 1 reply; 13+ messages in thread
From: Junio C Hamano @ 2025-12-14 23:27 UTC (permalink / raw)
  To: Koutsouflakis Stefanos; +Cc: Johannes Sixt, git@vger.kernel.org

Koutsouflakis Stefanos <koutsouflakis.stefanos@proton.me> writes:

> On Friday, December 12th, 2025 at 05:25, Junio C Hamano <gitster@pobox.com> wrote:
>
>> I doubt that special casing an empty tree would fly well.
>
> I might be missing something, could you say more about 
> what makes this problematic? 

Inconsistency.

Treating "newly added files" specifically is making the behaviour
inconsistent with others already, but doing so only when you haven't
created a commit or after doing "checkout/switch --orphan", which is
essentially what special-casing an empty tree case is about, makes
it even more inconsistent.

> If it is about breaking existing workflows: any script that 
> automates either of the two use-cases discussed would be relying 
> on behavior that is almost certainly unintended.

I do not think that is the reason for "special casing an empty tree
would not fly well", but I have to say your view is too narow.  I do
rely on "reset --hard && clean -f -x" working in order to make the
working tree spiffy clean, and I somehow doubt I am in the minority.
And "reset --hard" MUST not fail in such a case.

> Such scripts 
> would fail, but without data loss, and give authors a clear 
> signal to fix a likely bug. 

And most authors will consider the "bug" to be fixed is in the
degraded behaviour of "reset --hard". that does not do what is
written on the label  Then what?


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC] reset --hard: warn before discarding staged content with no commit history
  2025-12-14 23:27           ` Junio C Hamano
@ 2025-12-15  7:22             ` Koutsouflakis Stefanos
  0 siblings, 0 replies; 13+ messages in thread
From: Koutsouflakis Stefanos @ 2025-12-15  7:22 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Sixt, git@vger.kernel.org

On Monday, December 15th, 2025 at 01:27, Junio C Hamano <gitster@pobox.com> wrote:

> Inconsistency.
> 
> Treating "newly added files" specifically is making the behaviour
> inconsistent with others already, but doing so only when you haven't
> created a commit or after doing "checkout/switch --orphan", which is
> essentially what special-casing an empty tree case is about, makes
> it even more inconsistent.
> 
> > If it is about breaking existing workflows: any script that
> > automates either of the two use-cases discussed would be relying
> > on behavior that is almost certainly unintended.
> 
> 
> I do not think that is the reason for "special casing an empty tree
> would not fly well", but I have to say your view is too narow. I do
> rely on "reset --hard && clean -f -x" working in order to make the
> working tree spiffy clean, and I somehow doubt I am in the minority.
> And "reset --hard" MUST not fail in such a case.
> 
> > Such scripts
> > would fail, but without data loss, and give authors a clear
> > signal to fix a likely bug.
> 
> 
> And most authors will consider the "bug" to be fixed is in the
> degraded behaviour of "reset --hard". that does not do what is
> written on the label Then what?

That actually makes sense. For tools as versatile as Git, it is
sometimes hard to see the bigger picture and the different ways 
of people using it. 
I'll drop the proposal, and thanks everyone for your time.

-- Stefanos

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-12-15  7:23 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-10 15:01 [RFC] reset --hard: warn before discarding staged content with no commit history Koutsouflakis Stefanos
2025-12-11  3:24 ` Junio C Hamano
2025-12-11  3:59   ` Eric Sunshine
2025-12-11  5:25     ` Junio C Hamano
2025-12-11 11:53   ` Koutsouflakis Stefanos
2025-12-11 12:22     ` Johannes Sixt
2025-12-11 16:33       ` Koutsouflakis Stefanos
2025-12-12  3:24       ` Junio C Hamano
2025-12-14 13:29         ` Koutsouflakis Stefanos
2025-12-14 13:45           ` Štefan Balog
2025-12-14 23:27           ` Junio C Hamano
2025-12-15  7:22             ` Koutsouflakis Stefanos
2025-12-12 22:14 ` D. Ben Knoble

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 NNTP newsgroup(s).