[RFC] Add git pull --hard mode - #2384
Conversation
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>
Welcome to GitGitGadgetHi @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:
You can CC potential reviewers by adding a footer to the PR description with the following syntax: NOTE: DO NOT copy/paste your CC list from a previous GGG PR's description, 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:
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 patchesBefore 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 Both the person who commented An alternative is the channel Once on the list of permitted usernames, you can contribute the patches to the Git mailing list by adding a PR comment If you want to see what email(s) would be sent for a 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 curl -g --user "<EMailAddress>:<Password>" \
--url "imaps://imap.gmail.com/INBOX" -T /path/to/raw.txtTo 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): To send a new iteration, just add another PR comment with the contents: 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, |
|
/allow |
|
Error: User taahol is not yet permitted to use GitGitGadget |
|
/allow |
|
User ArturBieniek4 is now allowed to use GitGitGadget. |
|
Allow |
|
/submit |
|
It seems nothing happened as this workflow failed: https://github.com/gitgitgadget-workflows/gitgitgadget-workflows/actions/runs/32055421327 @rimrul |
|
Yes, it couldn't process the |
|
/submit |
|
Submitted as pull.2384.git.git.1787052873141.gitgitgadget@gmail.com To fetch this version into To fetch this version to local tag |
|
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. |
|
Thanks for the feedback.
I agree that whether replacing local history belongs under git pull is a
separate design question, and I understand the distinction you are
making between integration and replacement.
I am less convinced, though, by the more general argument that
destructive operations should intentionally remain inconvenient. Git
already exposes explicitly destructive operations as single commands,
with git push --force being perhaps the clearest example. In that case
the possible loss may even affect shared remote history rather than only
local state.
My thinking with git pull --hard was similar: make the destructive
behavior explicit in the option name, while allowing pull to perform the
fetch and validate that there is exactly one integration candidate
before resetting to it. That seemed preferable to users encoding the
same operation in aliases or scripts around fetch and reset --hard.
That being said, I understand the objection that a hard reset is
fundamentally not history integration, and therefore may simply not
belong under git pull.
Thanks.
…On 8/18/26 5:00 PM, gitgitgadget-git[bot] wrote:
*gitgitgadget-git[bot]* left a comment (git/git#2384) <https://
github.com/git/git/pull/2384#issuecomment-5330024246>
*Junio C Hamano* wrote on the Git mailing list <https://lore.kernel.org/
***@***.***> (how to reply to this email <https://
gitgitgadget.github.io/reply-to-this>):
"Artur Bieniek via GitGitGadget" ***@***.***> writes:
> From: Artur Bieniek ***@***.***>
>
> 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.
—
Reply to this email directly, view it on GitHub <https://github.com/git/
git#2384?
email_source=notifications&email_token=AGHNA4GXE55EO4U53ZFSLYD5KRVRHA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMZTGAYDENBSGQ3KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5330024246>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AGHNA4BTO5YR56RXGADWHMT5KRVRHAVCNFSNUABBKJSXA33TNF2G64TZHMZTMNJQGI5US43TOVSTWNJRGU2DENBZG43TBILWAI>.
You are receiving this because you were mentioned.Message ID: <git/git/
***@***.***>
|
|
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 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. |
|
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. |
Hmm, whose mailbox? But if that was Again, I'm far from an expert in these things, so… |
|
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.
> |
|
User |
|
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. |
|
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. |
|
"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.
> ... |
|
User |
|
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.
|
|
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 |
|
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"?
|
cc: Phillip Wood phillip.wood123@gmail.com
cc: "Kristoffer Haugsbakk" kristofferhaugsbakk@fastmail.com