Fossil Forum

Command equivalent to git reset? (clear all staged changes)
Login

Command equivalent to git reset? (clear all staged changes)

Command equivalent to git reset? (clear all staged changes)

(1) By anonymous on 2020-04-22 06:00:52 [source]

I frequently forget what a directory tree actually has and absent-mindedly fossil add the directory recursively. This almost always adds a lot of files I don't want yet so I reflexively fossil rm the directory, which then removes a lot of files I do want. After that I go in one by one to cancel all add/removes until I just have the 3 files I actually wanted in the commit.

In git you can do git reset which cancels/clears all staged changes. I've looked into fossil's commands and found nothing like it. It seems simple and obvious so I'd be surprised if fossil didn't have it already.

(2) By Stephan Beal (stephan) on 2020-04-22 06:37:07 in reply to 1 [link] [source]

After that I go in one by one to cancel all add/removes

Presumably you mean calling fossil rm for each unwanted addition? rm can be used after a file is added, but before it is committed, to cancel the addition of that file.

This almost always adds a lot of files I don't want yet so I reflexively fossil rm the directory, which then removes a lot of files I do want.

"Reflexively" and "rm" generally don't go well together.

In git you can do git reset which cancels/clears all staged changes. I've looked into fossil's commands and found nothing like it.

Fossil has no staging area/step.

Perhaps you're looking for revert:

[stephan@lapdog:~/fossil/fossil]$ f rm configure 
DELETED configure
[stephan@lapdog:~/fossil/fossil]$ f revert configure 
REVERT   configure
 "fossil undo" is available to undo changes to the working checkout.

Many commands are supported by fossil undo, but only 1 level of undo is available, and add/rm apparently do not support undo. Use rm to "undo" unwanted adds.

(3) By Richard Hipp (drh) on 2020-04-22 10:37:12 in reply to 1 [link] [source]

Fossil does not have a "staging area" in the same sense that Git does. With Fossil, you "add" a file just once. "fossil add" simply tells the system that you want to track this file. You do not need to "fossil add" the file before every commit like you do with Git. You "fossil add" one time, and it remembers that forever (or until you "fossil rm" it).

So you "fossil add" the first time you are adding a file to the project. But thereafter, you simply "fossil commit" and Fossil will automatically detect when you have edited the file and record the changes.

Doing "fossil commit" is like doing "git commit -a". The "-a" option is always there.

In Fossil, if you want to commit just a few of the files you have edited, then you simply list the files that you want to commit on the command-line. Example: "fossil commit src/file1.c doc/doc2.md". When you enter "fossil commit" with no arguments, it automatically commits every file that has been edited.

(4) By Andy Bradford (andybradford) on 2020-04-22 14:09:51 in reply to 1 [link] [source]

> It seems simple and obvious so  I'd be surprised if fossil didn't have
> it already.

You mean as simple as "fossil revert"?

$ fossil addremove
ADDED  file.1
ADDED  file.10
ADDED  file.2
ADDED  file.3
ADDED  file.4
ADDED  file.5
ADDED  file.6
ADDED  file.7
ADDED  file.8
ADDED  file.9
added 10 files, deleted 0 files

Oops, I didn't want all that:

$ fossil revert
UNMANAGE file.1
UNMANAGE file.10
UNMANAGE file.2
UNMANAGE file.3
UNMANAGE file.4
UNMANAGE file.5
UNMANAGE file.6
UNMANAGE file.7
UNMANAGE file.8
UNMANAGE file.9


Maybe this is what you're looking for?

Andy

(5) By anonymous on 2020-04-22 14:46:52 in reply to 4 [link] [source]

No, revert reverts all changes made since the last commit. What I want is something that unadds all added files and adds in all rm-ed files in a way, to cancel all proposed file addition/removal operations. It wouldn't alter any files physically.

Effectively a revert without actually changing any of the files on disk.

(I think) this is close to what I'm looking for, though.

(6) By Stephan Beal (stephan) on 2020-04-22 15:27:48 in reply to 5 [link] [source]

What I want is something that unadds all added files and adds in all rm-ed files in a way, to cancel all proposed file addition/removal operations.

There isn't currently a command for that. To the best of my recollection, since 2008 there's never(?) been a post that specific use case.

That said, it wouldn't be difficult to do, but i have doubts about the general utility of it, given that this is the first(?) time it's come up.

(7.1) By Martin Gagnon (mgagnon) on 2020-04-22 15:34:46 edited from 7.0 in reply to 6 [link] [source]

It happens to me in the past that I would have benefit from such feature.

What I end up doing in case like this is something like this:

fossil change > temp.txt
vim temp.txt      # edit and keep 1 file per line that I want to un-add
cat temp.txt | xargs fossil rm

Which is trivial for me, but may be not for everybody.

(8) By anonymous on 2020-04-22 17:32:18 in reply to 7.1 [link] [source]

As a band-aid solution the following two one liners can be used:

If a lot of unneeded files were added:

fossil changes | awk '/ADDED/ {$1=""; print $2}' | xargs fossil rm

If a lot of needed files were removed:

fossil changes | awk '/DELETED/ {$1=""; print $2}' | xargs fossil add

Of course these aren't really ideal and require a Unixy system, but they work!

(10) By Stephan Beal (stephan) on 2020-04-22 18:41:05 in reply to 7.1 [link] [source]

Going solely from memory about how the checkout db works, this sounds easy to do, but a name for the command doesn't spring to mind. Suggestions? Not "reset" - that might leave a false impression of git compatibility.

All the command would do is remove (from the checkout db) all newly-added entries and reset all rm'd entries, without actually touching the files. Only the checkout db would be affected.

i'll take a look at adding (as it were) it, with the minor caveat that it would remain in a branch until after the upcoming release.

(11) By Stephan Beal (stephan) on 2020-04-22 18:55:29 in reply to 10 [link] [source]

but a name for the command doesn't spring to mind. Suggestions? Not "reset" - that might leave a false impression of git compatibility.

"nevermind"? "unaddremove"? "unreflexively"?

(12.1) By Stephan Beal (stephan) on 2020-04-22 19:21:17 edited from 12.0 in reply to 7.1 [link] [source]

Just to confirm before i check this in (noting that it still doesn't have a great name), this is essentially what you guys would like, correct?

[stephan@lapdog:~/fossil/fossil]$ f changes
EDITED     src/add.c
[stephan@lapdog:~/fossil/fossil]$ f rm configure; f add x.json
DELETED configure
ADDED  x.json
[stephan@lapdog:~/fossil/fossil]$ f changes
DELETED    configure
EDITED     src/add.c
ADDED      x.json
[stephan@lapdog:~/fossil/fossil]$ f unaddremove
[stephan@lapdog:~/fossil/fossil]$ f changes
EDITED     src/add.c

:-?

Edit:

[stephan@lapdog:~/fossil/fossil]$ ./fossil help unaddremove
Resets the ADD/REMOVE state of a checkout, such that all newly-added
(but not yet committed) files are no longer added and newly-removed
(but not yet committed) files are no longer removed.

This command affects only the checkout database, not the checkout's
files.

(13) By anonymous on 2020-04-22 22:22:59 in reply to 12.1 [link] [source]

Just to confirm before i check this in (noting that it still doesn't have a great name)

Maybe it should do "unadd" and "undelete" separately? This will also make the naming of the commands more consistent.

Alternatively, this looks like a partial "revert". Maybe this should be controlled by switches to "revert" command (--adds-only, --deletes-only, --keep-edits)?

(14) By Stephan Beal (stephan) on 2020-04-22 23:59:00 in reply to 13 [link] [source]

Maybe it should do "unadd" and "undelete" separately? This will also make the naming of the commands more consistent.

If i hadn't already implemented it i'd probably tend to agree ;). Given the extremely limited scope of its applicability, splitting it up currently feels a bit like overkill (but my mind may have changed by tomorrow).

FWIW, the feature request was for one command which does this, not two ;).

"undelete" would possibly give false expectations about its ability to undelete files. It can un-"remove" them, restoring (if needed) their contents from the current checkout version of the repo, but it can't un-"delete" anything.

Alternatively, this looks like a partial "revert". Maybe this should be controlled by switches to "revert" command (--adds-only, --deletes-only, --keep-edits)?

That is a valid argument, but i'm not currently comfortable with touching revert this way. The revert logic, by comparison, is much more complex and does a lot of work unrelated to/unnecessary for the un-add/un-rm features.

The "easy" implementation of this feature is only about 6 lines of code, but it turns out that the un-rm requires special cases which blow it up by more than 6x:

  1. If a rm'd file is missing (e.g. via fossil rm --hard), it's restored from the current checkout version of the repo.

  2. If an rm'd file is not missing then it is retained as-is, rather than restored from the checkout version. This is necessary for keeping any local modifications for such files.

Checking for both of those cases requires handling the case that the new command is run from a subdirectory of the checkout, which means converting all paths to relative ones. If we didn't have those 2 cases to deal with, the implementation would be much simpler (only 2 SQL commands) and we'd not have to do any filename/file handling at all.

In any case, i'm not keen on shoehorning these into the revert machinery, though the argument of adding them as flags for that command does sound compelling.

It's quickly approaching 2am here, so it's time to check it in before bed:

https://fossil-scm.org/fossil/timeline?r=unaddremove-command

Noting that "unaddremove" is only a "working title" - hopefully we'll find a better name or maybe i can be convinced to split it into two (but don't currently feel compelled to do so). Or maybe we add it as a flag to addremove, e.g. addremove --undo or addremove --invert or addremove --no-no-no?

Its usage/results currently look like:

[stephan@lapdog:~/fossil/fossil]$ f rm --hard configure src/main.c; f add x.json
DELETED configure
DELETED src/main.c
DELETED_FILE /home/stephan/fossil/fossil/configure
DELETED_FILE /home/stephan/fossil/fossil/src/main.c
ADDED  x.json
[stephan@lapdog:~/fossil/fossil]$ f changes
DELETED    configure
EDITED     src/add.c
DELETED    src/main.c
ADDED      x.json
[stephan@lapdog:~/fossil/fossil]$ f unaddremove -verbose
Un-added: ./x.json
Un-removed: ./configure
Un-removed: ./src/main.c
Un-removed 2 file(s).
Un-added 1 file(s).
[stephan@lapdog:~/fossil/fossil]$ l configure
-rwxrwxr-x 1 stephan stephan 130 Apr 23 01:44 configure

[stephan@lapdog:~/fossil/fossil/src]$ f addremove
...<big snip>...
added 67 files, deleted 0 files
[stephan@lapdog:~/fossil/fossil/src]$ f unaddremove
Un-added 67 file(s).

(15) By anonymous on 2020-04-23 00:44:55 in reply to 14 [link] [source]

I compiled the latest tarball from that snapshot and it's exactly what I was looking for! Thanks for the addition, this will definitely help when fixing my clumsiness.

(16) By Stephan Beal (stephan) on 2020-04-23 00:54:35 in reply to 15 [link] [source]

Just be aware that the name will certainly change. My current inclination is to make it a flag for the addremove command.

(18) By ravbc on 2020-04-23 09:20:30 in reply to 16 [link] [source]

Couldn't it be part of the undo command?

(35) By Andy Bradford (andybradford) on 2020-04-23 14:22:10 in reply to 16 [link] [source]

> My current inclination is to make it a flag for the addremove command.

I'm not sure if you saw my suggestion about it belonging to the "revert"
command. What are your thoughts on that?

Thanks,

Andy

(36) By Andy Bradford (andybradford) on 2020-04-23 14:23:43 in reply to 35 [link] [source]

Haha, apparently I didn't notice that you were actually replying to someone who had already suggested options for "revert". At any rate, I think "revert" is a more natural place.

Andy

(40) By Stephan Beal (stephan) on 2020-04-24 09:48:17 in reply to 36 [link] [source]

Haha, apparently I didn't notice that you were actually replying to someone who had already suggested options for "revert". At any rate, I think "revert" is a more natural place.

After experimenting with add|rm|addremove --reset, i prefer that approach because:

(if ^^^^ that line mis-renders, see /forumpost/8055955a18)

  1. It places the "undo" option in the same place as the command it's undoing.

  2. It allows us to use the same flag name for both adds and removes, while still providing the ability to run one or the other or both of the operations.

  3. It inherits the same "undo" behaviour as the corresponding command (namely, no undo behaviour, whereas revert uses undo).

Though i agree that revert is arguably a better semantic fit, the current approach seems to be a better fit in terms of usability.

(17) By anonymous on 2020-04-23 06:28:49 in reply to 14 [link] [source]

  1. If an rm'd file is not missing then it is retained as-is, rather than > restored from the checkout version. This is necessary for keeping any local modifications for such files.

The way I see this, when a file is reported as DELETED, then it's current disposition is still under VSC control until the commit. Whether user has kept the actual file or did the --hard should not have any effect on revert action. In both cases the last-current version is restored; just what the revert does now. Moreover, revert does allow "undo",thus those potential post-delete changes are not completely lost.

Looking at the revert code, the whole process is driven by torevert table. So it's just a matter of filtering the list by current status, based on the passed flags (--adds, --deletes). By the way, --keep-edits is effectively "stash".

Here's the relevant parts from update.c::revert_cmd(), and the filter condition for ADDED from checkin.c::status_report():isNew, here's the isManaged.

This kind of operation squarely fits the "revert", well, that's the only way to do it currently anyway...

The "undo" feature alone is too good a safeguard for this to bypass.

(19) By Stephan Beal (stephan) on 2020-04-23 10:17:28 in reply to 17 [link] [source]

The way I see this, when a file is reported as DELETED, then it's current disposition is still under VSC control until the commit. Whether user has kept the actual file or did the --hard should not have any effect on revert action. In both cases the last-current version is restored; just what the revert does now. Moreover, revert does allow "undo",thus those potential post-delete changes are not completely lost.

This command doesn't support undo, though, and i honestly don't want it to because i feel that the new command is the undo for a rare user error. My second pass of the implementation always restored the version from the checkout, but that can lead to data loss:

echo '# hi' >> configure
fossil rm configure
fossil unaddremove # would replace configure

so i opted for the strategy, "if the file exists, leave it alone, else restore it from the repo."

Though i try to convince myself that data loss in that case is the user's own fault, i can't bring myself to implement it in such a way that it loses their changes. The user is undo'ing the rm because they decided it was a mistake, and losing their changes via the un-rm operation simply Feels Wrong.

This is not revert, so it need not behave identically.

Looking at the revert code, the whole process is driven by torevert table. So it's just a matter of filtering the list by current status, based on the passed flags... This kind of operation squarely fits the "revert", well, that's the only way to do it currently anyway...

And "just" interleaving this new logic into that logic.

The fact that revert accepts optional filenames is a fundamental difference which cannot be hand-waved away. If this command accepts a list of filenames then i see literally zero benefit to it over the previous approach of manually invoking rm to cancel mis-adds and add to cancel mis-removes. i.e. the utility of this new command is the fact that it doesn't accept specific filenames - it globally wipes the slate clean.

That said: patches which integrate it with revert are welcomed - it's hard to argue with working code and the current code has already taken up about 2 more hours than i had expected to spend on this.

The "undo" feature alone is too good a safeguard for this to bypass

i disagree because:

  1. This feature is a special-case undo for a rare user-level mistake, invoked only in the case of that mistake. The potential for unwanted side-effects of undoing an undo makes me kind of queasy.

  2. Fossil supports only a single level of undo, and overwriting any existing undo with this state doesn't sit well with me - there may be something far more important sitting in the undo tables.

  3. This mistake can be recovered from with other standard commands which do not use undo, so adding explicit undo to this simplification of that process seems both unnecessary and undesirable.

After sleeping on it, my current preference is to move this feature to addremove --reset, since that's effectively what it does and gives it the git-like name from the top post, though that also admittedly hides it behind a command many people don't use. When invoked that way, addremove would accept no other arguments except --verbose and would simply reset the add/remove state.

(20.2) By Stephan Beal (stephan) on 2020-04-23 11:27:21 edited from 20.1 in reply to 19 [link] [source]

After sleeping on it, my current preference is to move this feature to addremove --reset...

Or...

fossil add --reset [--verbose]
fossil rm --reset [--verbose]
# edit:
fossil addremove --reset [--verbose] # runs both of the above

which would add some flexibility over a do-it-all command and would group the features in with what they're undoing.

Opinions?

Edit: i've implemented that and like it a lot better. It's easier for a user to find, doesn't require any new commands, and neatly bypasses the question of whether or not to use undo (as those commands do not use undo).

(21) By Martin Gagnon (mgagnon) on 2020-04-23 11:45:33 in reply to 20.1 [link] [source]

What about "—cancel"? It seems clearer than —reset.

And I would put it on all 3 sub-command: add, rm, and addremove.

After adding a subdir by mistake, I would do:

fossil add —cancel.

After doing a addremove before to update my ignore-glob. I would do

fossil addremove —cancel.

etc...

(22) By Richard Hipp (drh) on 2020-04-23 11:58:43 in reply to 20.2 [link] [source]

I prefer an option on an existing command, rather than creating yet another new command. I also like Martin's idea of --cancel rather than --reset.

(23) By Richard Hipp (drh) on 2020-04-23 12:00:04 in reply to 22 [link] [source]

Or, maybe --reset is better. I'm not sure....

(38) By Marcelo Huerta (richieadler) on 2020-04-23 16:49:06 in reply to 23 [link] [source]

I don't know, "--reset" sounds like a "git-ism" to me...

(33) By Andy Bradford (andybradford) on 2020-04-23 14:17:52 in reply to 22 [link] [source]

> I prefer an option on an existing command,

Now that I understand the request,  I was thinking along the same lines.
Maybe "fossil revert --newfilesonly" or something perhaps less verbose.

Andy

(34) By Andy Bradford (andybradford) on 2020-04-23 14:19:29 in reply to 33 [link] [source]

Or maybe "fossil revert --added" and "fossil revert --deleted" etc...

Andy

(37) By anonymous on 2020-04-23 15:25:12 in reply to 34 [link] [source]

Yep, it reads quite naturally and spells out the intent: "revert the added/deleted".

Though taking into account Stephan's preference to go on with expanding add/delete commands, perhaps this could be "add --deleted", "delete --added".

(39) By Stephan Beal (stephan) on 2020-04-23 17:27:04 in reply to 37 [link] [source]

Though taking into account Stephan's preference to go on with expanding add/delete commands, perhaps this could be "add --deleted", "delete --added".

Ideally they'd have the same name so that the same flags could be passed to all 3 of add, rm, and addremove. If they have different names for add and rm then both of those flags would need to be passed to addremove to get the same effect, which seems clumsy.

What exactly that name is, however, is more or less unimportant to me. "reset" was chosen only because the OP used that term. The top contenders so far are "reset" and "cancel". Y'all figure out what the flag should be named and it will get that name/those names, with Richard's vote taking priority.

(24) By Florian Balmer (florian.balmer) on 2020-04-23 12:00:22 in reply to 20.2 [link] [source]

Opinions?

Thanks for the addition, I see cases where this may be handy, and it's no longer necessary to resort to the ad hoc scripting methods mentioned in this forum thread.

It looks like the modified commands (add, rm, addremove) now have two "global" options (--verbose and --dry-run) that are no longer "global" (i.e. no longer valid for all code paths).

  • Regarding --verbose: shouldn't this be a no-op for the existing code paths (without --reset), such that --verbose is simply the default (and only) mode for the existing code paths?

  • Regarding --dry-run: shouldn't this be supported by the new --reset paths as well, especially since the operations can't be undone? This seems not too cumbersome to add (but only from looking at the code)?

(25) By Stephan Beal (stephan) on 2020-04-23 12:12:05 in reply to 24 [link] [source]

Very briefly from my phone at the post office...

Dry run would not work as-is with the un-rm code because it modifies files. It wouldn't be difficult to add, though. i'm ambivalent.

Verbose isn't used by the other paths, so enabling it for those seems like it might be confusing.

i chose the name reset because the OP used that term. Cancel is also good. Again - ambivalent.

(26) By Stephan Beal (stephan) on 2020-04-23 12:58:44 in reply to 24 [link] [source]

More info from back at the PC...

Regarding --verbose: shouldn't this be a no-op for the existing code paths

If we're going to allow the new --verbose to be a no-op for the non-reset commands, we might as well allow all other options to be no-ops for --reset, but that just seems sloppy to me.

i'll add --dry-run in a moment.

As far as the name goes, reset vs cancel, they both sound appropriate to me - just let me know which to use.

(27) By Florian Balmer (florian.balmer) on 2020-04-23 13:09:36 in reply to 26 [link] [source]

If we're going to allow the new --verbose to be a no-op for the non-reset commands, we might as well allow all other options to be no-ops for --reset, but that just seems sloppy to me.

Hm, not sure. The --verbose flag could be valid in any combinations, just with the old code paths already being in verbose mode by default, without a way to turn it off.

The other flags are incompatible with --reset, and the overly-correct way would be to abort with an error pointing out the invalid combination, as in this example?

(29) By Stephan Beal (stephan) on 2020-04-23 13:31:34 in reply to 27 [link] [source]

Hm, not sure. The --verbose flag could be valid in any combinations, just with the old code paths already being in verbose mode by default, without a way to turn it off.

Enabling it for the other commands doesn't add anything to the current feature and it would unnecessarily add a new, yet unused, flag to the existing features.

The other flags are incompatible with --reset, and the overly-correct way would be to abort with an error pointing out the invalid combination, as in this example?

Agreed, but it also seems like overkill. Reset/cancel is something fossil has never needed, and is being added to simplify recovery from a a one-in-a-million user error, not to fill a general-purpose need. The current implementation will fail if passed invalid flag combos, it just won't be very informative. The help text explains it, though, and that's where a user typically looks when flags fail.

(30) By Florian Balmer (florian.balmer) on 2020-04-23 13:48:36 in reply to 29 [link] [source]

... fail if passed invalid flag combos, it just won't be very informative.

The generic error message by verify_all_options() is not helpful in the case of incompatible flags, i.e. they will be referred to as invalid, which is not correct.

I still think the few additional simple checks to abort gracefully in case of incompatible flags are worth it, to match Fossil's usual behavior.

(31) By Stephan Beal (stephan) on 2020-04-23 13:56:12 in reply to 30 [link] [source]

The generic error message by verify_all_options() is not helpful in the case of incompatible flags, i.e. they will be referred to as invalid, which is not correct.

That's splitting hairs. Incompatible is just a specific case of invalid.

I still think the few additional simple checks to abort gracefully in case of incompatible flags are worth it, to match Fossil's usual behavior.

If we add this level of detail then we have to update those checks and the resulting message every time someone adds an unrelated new feature flag to add/rm/addremove. Someone implementing the future add --foo or rm --bar shouldn't need to care about whether --reset needs to explicitly reject that flag.

i feel that the help text suffices, especially for a corner-case feature like this, but patches are welcomed.

Dry-run was just committed.

(28) By Martin Gagnon (mgagnon) on 2020-04-23 13:12:44 in reply to 26 [link] [source]

As far as the name goes, reset vs cancel, they both sound appropriate to me - just let me know which to use.

Let see the definition of each word (using reset definition and cancel definition keywords on google):

reset

  • verb
    set again or differently.
    "I must reset the alarm"

    ...

cancel

  • verb
    decide or announce that (a planned event) will not take place.
    "he was forced to cancel his visit"

    ...

Pedantically, cancel sounds more appropriate, but reset is also okay.

(41) By anonymous on 2020-04-24 22:09:18 in reply to 28 [link] [source]

Reset works as far as "reset to the state of only including edits" or "reset to the clean state," but "cancel all planned additions/removals" also works.

(32) By Andy Bradford (andybradford) on 2020-04-23 14:15:47 in reply to 5 [link] [source]

> No, revert reverts all changes made since the last commit. 

Oh, I  see, you only  want Fossil to forget  about files that  have been
added but not yet committed, and leave  the rest of the changes to other
already committed  files alone. Seems I  misunderstood (probably because
of lack of intimate knowledge of "git reset"). :-)

Thanks for the clarification.

Andy

(9) By anonymous on 2020-04-22 18:28:51 in reply to 1 [link] [source]

Sounds similar to Allow reverting a managed directory-tree

fossil revert the-mistakenly-added-dir

would probably undo most of what you said you mistakenly added. Unless, some of the files in that dir you indeed want to add; those you could re-add manually.

The current way, could be a combination of a selective 'fossil stash save' (in case you have some uncommitted edits), then global 'fossil revert', followed by 'fossil stash pop'. Kind of round-about, but saves on scripting.