Sitelet https://github.com/git/git/pull/2384
Skip to content

[RFC] Add git pull --hard mode - #2384

Open
ArturBieniek4 wants to merge 1 commit into
git:masterfrom
ArturBieniek4:pull-hard
Open

[RFC] Add git pull --hard mode#2384
ArturBieniek4 wants to merge 1 commit into
git:masterfrom
ArturBieniek4:pull-hard

Conversation

@ArturBieniek4

@ArturBieniek4 ArturBieniek4 commented Aug 14, 2026

Copy link
Copy Markdown

cc: Phillip Wood phillip.wood123@gmail.com
cc: "Kristoffer Haugsbakk" kristofferhaugsbakk@fastmail.com

Add --hard as an explicit alternative to merge and rebase. After
fetching, require a single integration candidate and reset the current
branch, index, and working tree to it.

Preserve quiet and submodule recursion behavior, and reject options
that cannot be honored by a hard reset. Document the destructive
semantics and cover them in tests.

Signed-off-by: Artur Bieniek <ar2rekb@gmail.com>
@gitgitgadget-git

Copy link
Copy Markdown

Welcome to GitGitGadget

Hi @ArturBieniek4, and welcome to GitGitGadget, the GitHub App to send patch series to the Git mailing list from GitHub Pull Requests.

Please make sure that either:

  • Your Pull Request has a good description, if it consists of multiple commits, as it will be used as cover letter.
  • Your Pull Request description is empty, if it consists of a single commit, as the commit message should be descriptive enough by itself.

You can CC potential reviewers by adding a footer to the PR description with the following syntax:

CC: Revi Ewer <revi.ewer@example.com>, Ill Takalook <ill.takalook@example.net>

NOTE: DO NOT copy/paste your CC list from a previous GGG PR's description,
because it will result in a malformed CC list on the mailing list. See
example.

Also, it is a good idea to review the commit messages one last time, as the Git project expects them in a quite specific form:

  • the lines should not exceed 76 columns,
  • the first line should be like a header and typically start with a prefix like "tests:" or "revisions:" to state which subsystem the change is about, and
  • the commit messages' body should be describing the "why?" of the change.
  • Finally, the commit messages should end in a Signed-off-by: line matching the commits' author.

It is in general a good idea to await the automated test ("Checks") in this Pull Request before contributing the patches, e.g. to avoid trivial issues such as unportable code.

Contributing the patches

Before you can contribute the patches, your GitHub username needs to be added to the list of permitted users. Any already-permitted user can do that, by adding a comment to your PR of the form /allow. A good way to find other contributors is to locate recent pull requests where someone has been /allowed:

Both the person who commented /allow and the PR author are able to /allow you.

An alternative is the channel #git-devel on the Libera Chat IRC network:

<newcontributor> I've just created my first PR, could someone please /allow me? https://github.com/gitgitgadget/git/pull/12345
<veteran> newcontributor: it is done
<newcontributor> thanks!

Once on the list of permitted usernames, you can contribute the patches to the Git mailing list by adding a PR comment /submit.

If you want to see what email(s) would be sent for a /submit request, add a PR comment /preview to have the email(s) sent to you. You must have a public GitHub email address for this. Note that any reviewers CC'd via the list in the PR description will not actually be sent emails.

After you submit, GitGitGadget will respond with another comment that contains the link to the cover letter mail in the Git mailing list archive. Please make sure to monitor the discussion in that thread and to address comments and suggestions (while the comments and suggestions will be mirrored into the PR by GitGitGadget, you will still want to reply via mail).

If you do not want to subscribe to the Git mailing list just to be able to respond to a mail, you can download the mbox from the Git mailing list archive (click the (raw) link), then import it into your mail program. If you use GMail, you can do this via:

curl -g --user "<EMailAddress>:<Password>" \
    --url "imaps://imap.gmail.com/INBOX" -T /path/to/raw.txt

To iterate on your change, i.e. send a revised patch or patch series, you will first want to (force-)push to the same branch. You probably also want to modify your Pull Request description (or title). It is a good idea to summarize the revision by adding something like this to the cover letter (read: by editing the first comment on the PR, i.e. the PR description):

Changes since v1:
- Fixed a typo in the commit message (found by ...)
- Added a code comment to ... as suggested by ...
...

To send a new iteration, just add another PR comment with the contents: /submit.

Need help?

New contributors who want advice are encouraged to join git-mentoring@googlegroups.com, where volunteers who regularly contribute to Git are willing to answer newbie questions, give advice, or otherwise provide mentoring to interested contributors. You must join in order to post or view messages, but anyone can join.

You may also be able to find help in real time in the developer IRC channel, #git-devel on Libera Chat. Remember that IRC does not support offline messaging, so if you send someone a private message and log out, they cannot respond to you. The scrollback of #git-devel is archived, though.

@taahol

taahol commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

/allow

@gitgitgadget-git

Copy link
Copy Markdown

Error: User taahol is not yet permitted to use GitGitGadget

@rimrul

rimrul commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

/allow

@gitgitgadget-git

Copy link
Copy Markdown

User ArturBieniek4 is now allowed to use GitGitGadget.

@SirJosh1987

Copy link
Copy Markdown

Allow

@ArturBieniek4

Copy link
Copy Markdown
Author

/submit

@taahol

taahol commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

It seems nothing happened as this workflow failed: https://github.com/gitgitgadget-workflows/gitgitgadget-workflows/actions/runs/32055421327 @rimrul

@rimrul

rimrul commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Yes, it couldn't process the /submit comment.

@ArturBieniek4

Copy link
Copy Markdown
Author

/submit

@gitgitgadget-git

Copy link
Copy Markdown

Submitted as pull.2384.git.git.1787052873141.gitgitgadget@gmail.com

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-git-2384/ArturBieniek4/pull-hard-v1

To fetch this version to local tag pr-git-2384/ArturBieniek4/pull-hard-v1:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-git-2384/ArturBieniek4/pull-hard-v1

@gitgitgadget-git

Copy link
Copy Markdown

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

"Artur Bieniek via GitGitGadget" <gitgitgadget@gmail.com> writes:

> From: Artur Bieniek <ar2rekb@gmail.com>
>
> Add --hard as an explicit alternative to merge and rebase. After
> fetching, require a single integration candidate and reset the current
> branch, index, and working tree to it.

There may be a population of users who *never* make changes to their
history or working tree, and always want to "hard reset to the
updated upstream".  Doing so would be safe for them because they
create nothing in their tree whose loss matters.

Giving them a convenient and safe way to do so might be worth
considering, but the behavior is already safely and explicitly
achieved by running 'git fetch' followed by 'git reset --hard @{u}',
so I am not sure whether it is worth adding another way to do so.

More importantly, throwing it into 'git pull' feels very wrong.

The core purpose of 'git pull' is history integration.  The command
is designed to help those who make their own changes and advance
history.  Adding a destructive option to the command makes it easier
for them to trigger it by accident, and unlike the main target of
this new feature, they have things in their tree that they cannot
afford to lose to accidents or mistakes.

So, I am mildly against adding anything of this sort to 'git pull'.
For that matter, I am generally against making it convenient to
discard or destroy history.  I prefer to keep these destructive
operations explicit, e.g., "fetch + reset --hard".

Thanks.

@ArturBieniek4

ArturBieniek4 commented Aug 18, 2026 via email

Copy link
Copy Markdown
Author

@taahol

taahol commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

@ArturBieniek4

Please (re-)read https://gitgitgadget.github.io/reply-to-this. As the development of Git happens on the mailing list (rather than Github), it is not enough, unfortunately, to reply to that “bot-carried” message. Instead, you should find the original email from Junio and reply to that and make sure, in particular, that git@vger.kernel.org remains in the CC list.

Indeed, although you did reply via email, it was regrettably a wrong message you wrote your answer to. And even though people can see your reply here in Github, it is expected (and required) that such messages go to the list instead. That way, the list archive can form a comprehensive story on how the patches came about.

Thanks.

@ArturBieniek4

Copy link
Copy Markdown
Author

Thanks for help, I'm doing such a thing the first time so I'm sorry for my mistakes. I first replied correctly (at least I think) via email but the list rejected the message because it was in HTML. So I replied in plain text but somehow Thunderbird then decided to change the recipients (possibly I just did something wrong and did not realize). Also I got a reply from the GitHub bot "The recipient's mailbox is full and can't accept messages now.". I will RTFM carefully and try again tomorrow.
Thanks.

@taahol

taahol commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Also I got a reply from the GitHub bot "The recipient's mailbox is full and can't accept messages now.".

Hmm, whose mailbox? But if that was gitgitgadget@gmail.com, then no, AFAIK the gadget doesn't even read its mailbox so it's not an useful place to send anything.

Again, I'm far from an expert in these things, so…

@gitgitgadget-git

Copy link
Copy Markdown

Phillip Wood wrote on the Git mailing list (how to reply to this email):

On 18/08/2026 15:48, Junio C Hamano wrote:
> "Artur Bieniek via GitGitGadget" <gitgitgadget@gmail.com> writes:
> >> From: Artur Bieniek <ar2rekb@gmail.com>
>>
>> Add --hard as an explicit alternative to merge and rebase. After
>> fetching, require a single integration candidate and reset the current
>> branch, index, and working tree to it.
> > There may be a population of users who *never* make changes to their
> history or working tree, and always want to "hard reset to the
> updated upstream".  Doing so would be safe for them because they
> create nothing in their tree whose loss matters.
> > Giving them a convenient and safe way to do so might be worth
> considering, but the behavior is already safely and explicitly
> achieved by running 'git fetch' followed by 'git reset --hard @{u}',
> so I am not sure whether it is worth adding another way to do so.

I think if the design was slightly different so that it errored out by default if there were uncommitted changes then that would make it worth while as it is safer than "git fetch; git reset --hard @{u}" and would allow the user to carry over those changes with "--autostash". So to me something like

	git pull --reset [--discard-changes | --autostash]

would be a more convincing design.

> More importantly, throwing it into 'git pull' feels very wrong.
> > The core purpose of 'git pull' is history integration.  The command
> is designed to help those who make their own changes and advance
> history.  Adding a destructive option to the command makes it easier
> for them to trigger it by accident, and unlike the main target of
> this new feature, they have things in their tree that they cannot
> afford to lose to accidents or mistakes.

If it refused to reset by default when there were uncommitted changes would that be safe enough? Uncommitted changes would be protected and any local commits that become unreachable after the reset can still be retrieved from the reflog. It's not quite the same as integrating remote and local changes, but more like updating the working copy.

Thanks

Phillip

> So, I am mildly against adding anything of this sort to 'git pull'.
> For that matter, I am generally against making it convenient to
> discard or destroy history.  I prefer to keep these destructive
> operations explicit, e.g., "fetch + reset --hard".
> > Thanks.
> 

@gitgitgadget-git

Copy link
Copy Markdown

User Phillip Wood <phillip.wood123@gmail.com> has been added to the cc: list.

@gitgitgadget-git

Copy link
Copy Markdown

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

Phillip Wood <phillip.wood123@gmail.com> writes:

> I think if the design was slightly different so that it errored out by 
> default if there were uncommitted changes then that would make it worth 
> while as it is safer than "git fetch; git reset --hard @{u}" and would 
> allow the user to carry over those changes with "--autostash". So to me 
> something like
>
> 	git pull --reset [--discard-changes | --autostash]
>
> would be a more convincing design.
> ...
> If it refused to reset by default when there were uncommitted changes 
> would that be safe enough? Uncommitted changes would be protected and 
> any local commits that become unreachable after the reset can still be 
> retrieved from the reflog. It's not quite the same as integrating remote 
> and local changes, but more like updating the working copy.

Yup, but git pull --ff-only serves the "No development is done in
this repository; it is merely to keep the latest sources here"
audience just fine.

What you are suggesting may be *useful* for those who agree with
this statement:

    I do value my local changes because I haven't committed them,
    but I am willing to discard these changes and replace them with
    whatever the upstream did.

but I am not sure of the use case for a repository/working tree
that is managed in such a way.

@gitgitgadget-git

Copy link
Copy Markdown

Artur Bieniek wrote on the Git mailing list (how to reply to this email):

One case where --ff-only does not seem to cover that audience is when the upstream branch itself is rewritten.

For example, a checkout may contain no local development at all and only be used to track the latest state of an upstream branch, but if that branch is rebased or otherwise force-updated, git pull --ff-only will refuse to update it because the histories have diverged.

That seems like a reasonably natural use case for the behavior Phillip described: git pull --reset on a clean working tree would mean "make this checkout match the fetched upstream", while still refusing by default to discard uncommitted changes.

I also like that distinction better than my original --hard proposal, since the destructive working-tree behavior would no longer be implicit in the primary option.

Thanks,
Artur

On 8/20/26 5:59 PM, Junio C Hamano wrote:
> Phillip Wood <phillip.wood123@gmail.com> writes:
> >> I think if the design was slightly different so that it errored out by
>> default if there were uncommitted changes then that would make it worth
>> while as it is safer than "git fetch; git reset --hard @{u}" and would
>> allow the user to carry over those changes with "--autostash". So to me
>> something like
>>
>> 	git pull --reset [--discard-changes | --autostash]
>>
>> would be a more convincing design.
>> ...
>> If it refused to reset by default when there were uncommitted changes
>> would that be safe enough? Uncommitted changes would be protected and
>> any local commits that become unreachable after the reset can still be
>> retrieved from the reflog. It's not quite the same as integrating remote
>> and local changes, but more like updating the working copy.
> > Yup, but git pull --ff-only serves the "No development is done in
> this repository; it is merely to keep the latest sources here"
> audience just fine.
> > What you are suggesting may be *useful* for those who agree with
> this statement:
> >      I do value my local changes because I haven't committed them,
>      but I am willing to discard these changes and replace them with
>      whatever the upstream did.
> > but I am not sure of the use case for a repository/working tree
> that is managed in such a way.

@gitgitgadget-git

Copy link
Copy Markdown

"Kristoffer Haugsbakk" wrote on the Git mailing list (how to reply to this email):

On Thu, Aug 20, 2026, at 18:43, Artur Bieniek wrote:
> One case where --ff-only does not seem to cover that audience is when
> the upstream branch itself is rewritten.
>
> For example, a checkout may contain no local development at all and only
> be used to track the latest state of an upstream branch, but if that
> branch is rebased or otherwise force-updated, git pull --ff-only will
> refuse to update it because the histories have diverged.

I don’t understand what you need a branch for in that case. I just use
the remote-tracking branch in that case (`origin/main` e.g.).

PS: Bottom posting is strongly preferred on this list.

> ...

@gitgitgadget-git

Copy link
Copy Markdown

User "Kristoffer Haugsbakk" <kristofferhaugsbakk@fastmail.com> has been added to the cc: list.

@gitgitgadget-git

Copy link
Copy Markdown

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

Artur Bieniek <abieniek@antmicro.com> writes:

> One case where --ff-only does not seem to cover that audience is when 
> the upstream branch itself is rewritten.

It does, doesn't it?  

It is not like you want to always blindly follow them.  Rewound
upstream is w warning-worthy event that the user should be notified
rather loudly, I would expect.

@gitgitgadget-git

Copy link
Copy Markdown

Artur Bieniek wrote on the Git mailing list (how to reply to this email):

On 8/20/26 7:29 PM, Kristoffer Haugsbakk wrote:
> On Thu, Aug 20, 2026, at 18:43, Artur Bieniek wrote:
>> One case where --ff-only does not seem to cover that audience is when
>> the upstream branch itself is rewritten.
>>
>> For example, a checkout may contain no local development at all and only
>> be used to track the latest state of an upstream branch, but if that
>> branch is rebased or otherwise force-updated, git pull --ff-only will
>> refuse to update it because the histories have diverged.
> > I don’t understand what you need a branch for in that case. I just use
> the remote-tracking branch in that case (`origin/main` e.g.).
> > PS: Bottom posting is strongly preferred on this list.
> >> ...


The branch itself is not essential; the point is to update the checked-out working tree as well. git fetch updates origin/main, but leaves the checkout at the old commit.

If resetting does not belong under pull, would the inverse design be more appropriate, e.g. git reset --pull --hard, meaning “fetch the configured upstream and reset to it”? Or would making reset perform network I/O be undesirable for the same reason?

Thanks,
Artur

@gitgitgadget-git

Copy link
Copy Markdown

Junio C Hamano wrote on the Git mailing list (how to reply to this email):

Artur Bieniek <abieniek@antmicro.com> writes:

> If resetting does not belong under pull, would the inverse design be 
> more appropriate, e.g. git reset --pull --hard, meaning “fetch the 
> configured upstream and reset to it”? Or would making reset perform 
> network I/O be undesirable for the same reason?

Very true.  I wonder if the feature of git you should be looking at
for doing things like this is not "pull", "fetch", or "reset" but is
"alias"?


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants