# [RFC] reset --hard: warn before discarding staged content with no commit history

13 messages from 2025-12-10 to 2025-12-15. Participants: Koutsouflakis Stefanos, Junio C Hamano, Eric Sunshine, Johannes Sixt, D. Ben Knoble, Štefan Balog.
Thread: https://gitlist.dev/t/64608

## Koutsouflakis Stefanos, 2025-12-10 15:01

Subject: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <a5wKtD6Tn0gzcba1IEUhukYnXPHxMwPq6puQKIPywmjNufi5vc6vX-v5BpPJ7qj_zZsuXF5FiS2gbpsurWmVjoWHtMm8A-kAbaZyjMfrTcs=@proton.me>
URL: https://gitlist.dev/e/a5wKtD6Tn0gzcba1IEUhukYnXPHxMwPq6puQKIPywmjNufi5vc6vX-v5BpPJ7qj_zZsuXF5FiS2gbpsurWmVjoWHtMm8A-kAbaZyjMfrTcs%3D%40proton.me

```
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

```

## Junio C Hamano, 2025-12-11 03:24

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <xmqqldj9g0pj.fsf@gitster.g>
URL: https://gitlist.dev/e/xmqqldj9g0pj.fsf%40gitster.g
In-Reply-To: <a5wKtD6Tn0gzcba1IEUhukYnXPHxMwPq6puQKIPywmjNufi5vc6vX-v5BpPJ7qj_zZsuXF5FiS2gbpsurWmVjoWHtMm8A-kAbaZyjMfrTcs=@proton.me>

```
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.

```

## Eric Sunshine, 2025-12-11 03:59

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <CAPig+cSep7+i2R-DDK+B6p6c3gy2Ehvm4U5N_PwSR-yZF3n1hA@mail.gmail.com>
URL: https://gitlist.dev/e/CAPig%2BcSep7%2Bi2R-DDK%2BB6p6c3gy2Ehvm4U5N_PwSR-yZF3n1hA%40mail.gmail.com
In-Reply-To: <xmqqldj9g0pj.fsf@gitster.g>

```
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".

```

## Junio C Hamano, 2025-12-11 05:25

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <xmqqcy4lfv3k.fsf@gitster.g>
URL: https://gitlist.dev/e/xmqqcy4lfv3k.fsf%40gitster.g
In-Reply-To: <CAPig+cSep7+i2R-DDK+B6p6c3gy2Ehvm4U5N_PwSR-yZF3n1hA@mail.gmail.com>

```
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..

```

## Koutsouflakis Stefanos, 2025-12-11 11:53

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <0lbeTWjDGq8hINMi-lj65HLgAIlUNZe_tzANStd9xxHQqAyZaEnaA0yPzVeY_VcReQIKNjY7eBEUGwMGvlbZ-0W0QZpux22cIHnosa0eX_k=@proton.me>
URL: https://gitlist.dev/e/0lbeTWjDGq8hINMi-lj65HLgAIlUNZe_tzANStd9xxHQqAyZaEnaA0yPzVeY_VcReQIKNjY7eBEUGwMGvlbZ-0W0QZpux22cIHnosa0eX_k%3D%40proton.me
In-Reply-To: <xmqqldj9g0pj.fsf@gitster.g>

```
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



```

## Johannes Sixt, 2025-12-11 12:22

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <d318c46c-fbc3-4e47-8c3f-165ca9a26225@kdbg.org>
URL: https://gitlist.dev/e/d318c46c-fbc3-4e47-8c3f-165ca9a26225%40kdbg.org
In-Reply-To: <0lbeTWjDGq8hINMi-lj65HLgAIlUNZe_tzANStd9xxHQqAyZaEnaA0yPzVeY_VcReQIKNjY7eBEUGwMGvlbZ-0W0QZpux22cIHnosa0eX_k=@proton.me>

```
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


```

## Koutsouflakis Stefanos, 2025-12-11 16:33

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <lVqXkS_Nc_hxtxMq3nevB6dCfPgh-qw9A6dLROQqGqN1_iqDONXeGQmp91hGmVTmaSIqGy5QVMC5OuzJmuULP-rUWcqBSv_L8pnLgPjoDsM=@proton.me>
URL: https://gitlist.dev/e/lVqXkS_Nc_hxtxMq3nevB6dCfPgh-qw9A6dLROQqGqN1_iqDONXeGQmp91hGmVTmaSIqGy5QVMC5OuzJmuULP-rUWcqBSv_L8pnLgPjoDsM%3D%40proton.me
In-Reply-To: <d318c46c-fbc3-4e47-8c3f-165ca9a26225@kdbg.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

```

## Junio C Hamano, 2025-12-12 03:24

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <xmqqzf7ocrhk.fsf@gitster.g>
URL: https://gitlist.dev/e/xmqqzf7ocrhk.fsf%40gitster.g
In-Reply-To: <d318c46c-fbc3-4e47-8c3f-165ca9a26225@kdbg.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" :-/

```

## D. Ben Knoble, 2025-12-12 22:14

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <CALnO6CC=JpKBwJbLDeBkEF5e3SnqzEXwNH_W3S5Bzhz3DD14MQ@mail.gmail.com>
URL: https://gitlist.dev/e/CALnO6CC%3DJpKBwJbLDeBkEF5e3SnqzEXwNH_W3S5Bzhz3DD14MQ%40mail.gmail.com
In-Reply-To: <a5wKtD6Tn0gzcba1IEUhukYnXPHxMwPq6puQKIPywmjNufi5vc6vX-v5BpPJ7qj_zZsuXF5FiS2gbpsurWmVjoWHtMm8A-kAbaZyjMfrTcs=@proton.me>

```
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

```

## Koutsouflakis Stefanos, 2025-12-14 13:29

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <Ai2bA2Zt8bsexgQEIKg1vK7-SNNhTlsmmFp_gOJp8IKX9dJME7UC97EtqRhAUfD00sFmqRdHg9xgGW82rikrLIDUIswrUPr3RKm-LQgGuNY=@proton.me>
URL: https://gitlist.dev/e/Ai2bA2Zt8bsexgQEIKg1vK7-SNNhTlsmmFp_gOJp8IKX9dJME7UC97EtqRhAUfD00sFmqRdHg9xgGW82rikrLIDUIswrUPr3RKm-LQgGuNY%3D%40proton.me
In-Reply-To: <xmqqzf7ocrhk.fsf@gitster.g>

```
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

```

## Štefan Balog, 2025-12-14 13:45

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <CAJq5WQ5+LBNR11gC+XPT6Z1ZZQZ0HLXxtZdRDoS+wpDjAy2itA@mail.gmail.com>
URL: https://gitlist.dev/e/CAJq5WQ5%2BLBNR11gC%2BXPT6Z1ZZQZ0HLXxtZdRDoS%2BwpDjAy2itA%40mail.gmail.com
In-Reply-To: <Ai2bA2Zt8bsexgQEIKg1vK7-SNNhTlsmmFp_gOJp8IKX9dJME7UC97EtqRhAUfD00sFmqRdHg9xgGW82rikrLIDUIswrUPr3RKm-LQgGuNY=@proton.me>

```
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
>
>

```

## Junio C Hamano, 2025-12-14 23:27

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <xmqqwm2o8x0v.fsf@gitster.g>
URL: https://gitlist.dev/e/xmqqwm2o8x0v.fsf%40gitster.g
In-Reply-To: <Ai2bA2Zt8bsexgQEIKg1vK7-SNNhTlsmmFp_gOJp8IKX9dJME7UC97EtqRhAUfD00sFmqRdHg9xgGW82rikrLIDUIswrUPr3RKm-LQgGuNY=@proton.me>

```
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?


```

## Koutsouflakis Stefanos, 2025-12-15 07:22

Subject: Re: [RFC] reset --hard: warn before discarding staged content with no commit history
Message-ID: <inl6W-7dpE2-dCPugnjAM-X01zhKAp5niQNigtqe5EVKEMEy1KEPFegzDC1zjpm7etuqAoVjg1gUd8_5vFO90LhaGmzLc3HJTE4MREXtzH8=@proton.me>
URL: https://gitlist.dev/e/inl6W-7dpE2-dCPugnjAM-X01zhKAp5niQNigtqe5EVKEMEy1KEPFegzDC1zjpm7etuqAoVjg1gUd8_5vFO90LhaGmzLc3HJTE4MREXtzH8%3D%40proton.me
In-Reply-To: <xmqqwm2o8x0v.fsf@gitster.g>

```
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

```
