fhist(1)

πŸ“¦
version 1.21.D001 Β· 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– fhist(1) πŸ’– β€” file history

General Commands Manual · the manual page for fhist, bestie ✨


🌸 NAME 🌸

fhist β€” file history πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

fhist filename...  option...

fhist -Help

fhist -VERSion

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so, fhist is literally the program you use to keep track of all the successive versions of a file. like, every single change you ever made? it remembers. and you can get any one of those old versions back. obsessed.

the way this is useful, let me count the ways:

  1. you can make a whole series of tentative edits to the file, and if things go bad, just back up to the last "good" edit. no stress πŸ’…
  2. you can delete old subroutines and code from your file that are obsolete, but still be able to get them back later if a need for them ever comes up. it's giving "no, i'm not a hoarder, i'm archiving" ✨
  3. you can compare two versions of the file to see how you fixed some old problem, so you can check up on whether that fix was actually correct at a later date. accountability, periodt.
  4. you get a record of your remarks for each version, so you can quickly know what bugs were fixed and what features were implemented. receipts πŸ‘‘
  5. the date the file was last edited can be automatically stored in the file. cute!

fhist manipulates modules. a module is simply any text file that you're interested in keeping versions of. for example, a source file doit.c is a module, and so is a documentation file howto.doc. the module name includes the suffix of the file (like in those examples). however, pathnames are not part of a module name, so /usr/dbell/bar.c cannot be a legal module name. sorry bestie 😭 a module name is limited to 12 characters, since the fhist program needs two extra characters for its own purpose.

✨ Keyword Substitution ✨

it is possible to have information about the state of the file inserted into the file. see the -Modify and -No-Keywords options, below, for more info. 🧚


πŸ’… OPTIONS πŸ’…

the following options are understood:

  • -Path pathname β€” modules are stored in a directory, called the module storage directory. the default directory is FHIST, and therefore is located relative to your current directory. this is convenient when you're in a directory containing many modules and you want a local storage directory to contain just those modules. if you use the -p option, then you can locate the storage directory anywhere you choose. this is useful if you choose to have a common storage directory for all of your files, independent of where they actually are used.
the files inside of the storage directory should not be changed by you. doing so will probably corrupt your edit history, causing errors when you extract old revisions. 😱 for your information though, each module is stored as two files in the directory. the one with the .s suffix is a copy of the newest version of the module, with one extra line at the beginning. the one with the .e suffix is the edit history of the module, and contains the information needed to extract previous revisions of the module. thus if the edit history is ever corrupted, you will at least have the most recent version of the module. 🫢
  • -MaKe_Path β€” this option may be used to request that the path directory be created automatically if it does not yet exist. this works for both the directory specified by the -Path option, and for the default. intermediate directories will also be created if necessary. it's giving "i made it myself" ✨
  • -BINary β€” this option may be used to specify that the file is binary, that it may contain NUL characters. it is essential that you have consistent presence or absence of the -BINary option for each file when combined with the -CReate, -Update, -Conditional_Update and -Extract options. failure to do so will produce inconsistent results. 😭 note: this is different behaviour to the fcomp(1) option of the same name. note: the -BINary option does not imply the -No-Keywords option.
  • -CReate β€” to use the fhist program for the first time, you need to create your storage directory. therefore, cd to the directory where you want it to be, which is probably the directory containing the modules you want to save the revisions of. then create the directory FHIST (or some other name if you don't want to use the default name).

to start using a module under fhist, you must first use the -CReate option. this creates the initial edit for that module in the storage directory, with the contents of the specified module as the initial edit. thus, if you have a source file prog.c, then the command:

fhist prog.c -create

creates the initial edit of the module. as part of this process, you are asked to provide remarks about the file. these remarks can be seen later using the -List option (described below). after the remarks have been typed, the contents of the file are then saved. you can then delete the file prog.c if desired, and fhist would be able to recreate it later. or you can leave it there as the working copy of the module. main character energy, honestly πŸ’–

the -CReate option may be combined with the -Update or -Conditional_Update options to create the file if required.

  • -Update β€” to save another revision of the module, you use the -Update option. this updates the files in the storage directory to include the latest changes. remarks are again asked for so that you can document why you made this edit. thus, to continue the example, after editing prog.c, the command:
fhist prog.c -u

will save the changes as a new edit. this command compares the newest version of the module to the previous version, saves the differences in the .e file, and copies the new source to the .s file. at this point, you can once again delete the prog.c file if desired, and later get back either of the two versions of the program. slay 🌈

the fhist program handles quota or disk full problems during a create or update operation without damage occurring to the edit history files. if an edit cannot be completed because of such problems, the edit is backed out completely, and you will get an error message about the disk problem. there is no need for any error recovery in this case, other than retrying the update when more disk space is available. the fhist program also disables signals during the critical file operations, so you do not have to worry about damaging the edit history files because of attempts to quit out of the program. protective king πŸ‘‘

the -CReate option may be combined with the -Update or -Conditional_Update options to create the file if required.

  • -Input filename β€” in either the -CReate or -Update options, the file containing the new version of the module defaults to the same name as the module. in the example, the module prog.c was created and updated from the data in the file prog.c. when you wish the data to come from some other file, you can use the -Input option, which specifies the input file to use for the data. for example, if you wanted to update prog.c, but from a filename called newprog.c, then the command:
fhist prog.c -u -i newprog.c

would save a new revision of module prog.c, but with the data that was in the file newprog.c. in this case, the file prog.c does not have to exist, and isn't referenced even if it did exist. again, once the update is complete, you could delete the newprog.c file if desired and then later you can retrieve its contents. πŸ’œ

  • -Remarks β€” remarks can be read from a file instead of from the terminal. the -Remarks option can be used to specify a file name containing the remarks. if there is no file name following the -Remarks option, then no remarks at all are used. the command:
fhist prog.c -u -r

would create a new revision of prog.c without asking for or saving any remarks about the edit. silent but effective πŸ™ˆ

  • -Remark_String text β€” it is also possible to specify the remarks directly on the command line. you may only use this option once. ✨
  • -Extract [ edit ] β€” to retrieve a previous revision of a module, you specify the name of the module and use the -Extract option to specify the edit number you want retrieved. edit numbers are assigned sequentially starting with 1. thus the initial version of the module has edit number 1, the first revision has edit number 2, and so on until the latest revision. if the -Extract option is not used, or if no edit number is supplied for it, then the latest edit number is extracted. therefore, this is the default action if no options at all are specified. 😌

edit numbers can also be zero, negative, or be a name with an optional offset. the number zero represents the latest edit number, and negative numbers indicate edit numbers backwards from the latest edit number. edit names represent edit numbers whose name had been set by using the -Name option. for example, if edit number 10 was associated with the name foo, then the edit name foo represents 10, foo-4 represents edit number 6, and foo+2 represents edit number 12. the special reserved names oldest and newest refer to the oldest and newest versions of the module in the edit history. πŸ¦‹

as an example of retrievals, assume that you have saved ten versions of the module prog.c. the following commands will then extract the versions of the file with the specified edit numbers:

fhist prog.c

version 10 (the latest)

fhist prog.c -e 9

version 9 (the version just prior)

fhist prog.c -e oldest

version 1 (the oldest version)

fhist prog.c -e -2

version 8 (latest version - 2)

the output filename is again defaulted to the module name. so when the module prog.c is extracted, the specified version of the module is written to the prog.c file. πŸŽ€


more of this page is coming, bestie β€” don't go anywhere πŸ’–

okay so about the overwriting thing, bestie β€” to stop you from accidentally nuking a file, fhist will by default ask you if overwriting is permitted when that would happen. The classic oopsie goes like this: you edit prog.c, then you try to update the module, but you forget to specify the -u option. Then fhist would try to extract the newest version of the module, and thus overwrite the file with the new changes 😭. Asking the question gives you a second to notice your mistake and prevent the overwriting. protective behavior fr fr πŸ’–

πŸ’Ύ -Output filename

You can change the output filename using the -Output option. So this command:

fhist prog.c -o newprog.c

will extract the latest version of the module prog.c, and put it into the file newprog.c. And once again β€” the file prog.c is ignored, whether or not it existed. πŸ‘»

πŸ”₯ -Force_Write

Forces overwriting of the file, so it never asks you if overwriting is permitted. Often useful in shell scripts, or when you're sure you want to overwrite any existing file. πŸ’…

πŸ›‘ -No_Write

The no-overwrite option β€” any existing files just won't be overwritten, again without asking you. Useful if you already have some of the modules in your directory, and you wanna extract the rest of the modules without overwriting the ones you already have. 🫢

⚠️ Specifying both -Fore_Write and -No_Write is an error.

πŸ“Ί -Terminal [ edit ]

Outputs an extracted module to the standard output, instead of writing it to a file. Great for viewing the beginning of a version of the file. πŸ‘€ You can interrupt it if you don't wanna see the whole file.

πŸŽ€ -Modify number

When extracting a file, fhist looks for and updates special character sequences in the first few lines of the file. These special sequences are for documentation purposes, like describing the edit number the file is from. For speed of extraction and updating, these sequences are usually limited to the first 25 lines of the file, since then fhist doesn't have to examine the entire file. The -Modify option can be used to change the number of lines to be modified from the default value of 25. Specifying zero totally disables the special character sequences, whereas specifying a very large number will cause the sequences to be checked for each line of the file (and thus slow fhist down 🐌).

Each special sequence is of the form:

[# keyword value, keyword value, ..., keyword value #]

where each keyword describes an item, and each value is the value for the preceding keyword. The keywords can be in upper or lower case, or both. The single space following the [#, following each comma, and preceding the #] must be present. If the sequence is wrong, an unknown keyword is used, the line is longer than 200 characters, or more than four keywords are used, then the whole line will not be changed. The current keywords which can be used are:

  • edit β€” the edit number
  • date β€” the date that the edit was created
  • user β€” the user name of the user who created the edit
  • module β€” the module name

In order to use this special character sequence, you just insert it into your module inside a comment (within the first few lines). When that's done, the value parts of the sequence can be null. For example, if you wanna put a special sequence into a program called delete.c, then you could edit the first few lines like this:

/*
 * Delete - program to delete files
 * [# Edit, Date #]
 */

When an extract is done, the proper edit number and date are automatically inserted as the new values. So if you extract edit 23 of the module delete.c which had been created on 8 August 89, then the resulting file would begin:

/*
 * Delete - program to delete files
 * [# Edit 23, Date 8-Aug-89 #]
 */

When updating a module, it's never necessary to edit these sequences, since any old values will be removed and replaced with the new ones. Also, when using the -d or -du options (described below), lines with these sequences compare as if the values were null, and thus will not cause spurious differences. ✨

During an update, the special character sequences are read and any edit value found is compared against the current edit number of the module. If they differ, then the update fails. This provides an interlock check for the case of two users extracting the same version of a file, editing it, and then both updating it without knowledge of each other πŸ™ˆ. In this case, the second user would fail, and then he can merge his edits with the previous user's edit and then retry the update. This checking is disabled if there is no special character sequence containing the edit keyword, the edit number value is null, or if the -Forced_Update option is used to indicate that the check is not needed.

πŸ™… -No_Keywords

Disables the use of the keyword special character sequences described above. Text containing keyword sequences is treated as plain text. Note: the -No_Keywords option does not imply the -BINary option.

🏷️ -Name string

Associates a name for the newest version of a module. It can be given along with the -CReate, -Update, or -Difference_Update options, to specify a name for the new version of the module. It can also be given by itself in order to specify a name for the newest version of a module. Each edit number can have many names associated with it, so this will not remove any previously defined name for the edit. Super useful for correlating many modules together. Like, when a new version of a program is ready to be released, you could give each module of the program the same name release1. Then in the future, you can recreate the sources making up that release by extracting the edits with the name release1 for every module. Edit names cannot begin with a digit, and cannot contain plus or minus signs. These rules prevent ambiguous parsing of edit numbers for the -Extract, -Terminal, -ALL, and -List options. 🌈

πŸ“‹ -List [ edit1 [ edit2 ]]

Prints a list of edits for the module, giving the user name, date, user remarks, and names specified for the edits. No edit number supplied β†’ all edits are printed in reverse order. A single edit number supplied β†’ only that edit number is printed. Two edit numbers supplied β†’ all edits in the specified range are printed. The output from this option defaults to the terminal. You can use the -Output option to save the results to a file. πŸ’–

πŸ” -Difference [ edit1 [ edit2 ]]

Displays the differences between two versions of a module, or between a file and a version of a module. There are three modes for this action, depending on how many edit numbers are supplied. These modes are illustrated by the following examples:

fhist foo.c -d
        Compare latest version against file "foo.c"

fhist foo.c -d 3
        Compare version 3 against file "foo.c"

fhist foo.c -d 3 4
        Compare version 3 against version 4

This option accepts the -Input option to specify the file to be compared. When using the -Difference option, the output defaults to the terminal. Therefore, you must use -Output if you wish the differences saved to a file. Using -Quick with -Difference will only output a quick summary of the changes, instead of the detailed changes β€” and that summary only supplies the number of lines inserted, deleted, and unchanged between the files. Using -What with -Difference will display all of both files, showing in detail what the differences are using change bars. πŸ”₯

The -Difference option may need to write one or two temporary files in order to extract old versions of a module to be compared. These files have names like T$n_nnn. They are deleted again just before differences are output, so that stopping the output before it is complete will not leave these files around. The temporary files are usually written to the current directory. If this is not reasonable because of permission or quota problems, then you can specify the directory for writing the temporary files into β€” this is done by defining the TMPDIR environment variable to be the path of the directory. πŸ“

πŸ”„ -Difference_Update

Combines the effects of the -Difference and -Update options. It displays the differences between a file and the latest version of a module. If there are any differences, it then proceeds to perform an update of the module with that file, asking for remarks as usual. This option is very useful when used with wildcarded module names. Then you can update just those modules which were changed by an edit session, and see the changes for each module before typing the appropriate remark for each module. 😌

You may specify both of the -Difference and -Update options, or you may use this option. The results are identical. periodt.

πŸ€” -Conditional_Update

Conditionally updates a module. That is, it will only do an update if there are any differences between a file and the latest version of a module. Convenient when related changes are made to many modules in a directory, and one command using wildcards can update just those modules that were changed. πŸ¦‹

The -CReate option may be combined with the -Update or -Conditional_Update options to create the file if required.

  • -CLean β€” bestie this one is literally the cleanup crew 🧹. It deletes any file that matches the newest version of a module. If a file exists that matches the newest version of a module, it gets deleted; if not, it stays. Perfect for tidying up a work directory after you've built a fresh version of a product. It's especially iconic when you pair it with -ALL. It'll also take the -Input option so you can point it at a directory holding the files to be cleaned.
  • -CHeck β€” this is the vibe check πŸ‘€. It finds out whether a file doesn't match the latest version of a module, and if it doesn't match, it says something. If the file does match? Silence. Nothing. Zero output. So it's your go-to for figuring out which files have been modified and are in need of updating. -ALL is defaulted for this option, because usually you want this for all the modules. For example,
fhist -CHeck

will report on all files which are different than the latest modules. If you also throw in -Quick, then the output is just the module names and nothing else β€” no extra chatter. That's the move for the backquote operator in shell scripts when you need to reference the modules that are out of date. -CHeck also accepts the -Input option.

  • -PRune edit β€” ok this one is serious, no cap πŸ’€. It permanently removes early edits from an edit history. Why would you want that? To cut down the disk space an edit history file is eating, or when you want to start another release of a file and want a copy of the edit history file for that new release. The option takes an edit number to preserve, and every edit in the edit history file before that edit gets deleted and can no longer be referenced. So if you wanted to keep only the current edit plus the previous 10 edits of the module file, you'd run:
fhist file -prune -10

Since -PRune is unrecoverable (unless you've got backup files lying around), fhist asks you to verify that you really, truly want the prune. You can use the -Forced_Update option to bypass that verification. πŸ™ˆ

  • -ALL β€” this one works with any of the action options, and it means: do the thing for all the modules in the module storage directory. Or, alternatively, you can name multiple module names on the command line and the actions get performed on those. But bestie β€” you cannot specify both -ALL and module names. Pick a lane βœ‹.

When you're using multiple modules or -ALL, the -Input and -Output options mean something slightly different. In those cases, the -Input and -Output arguments are a directory name containing filenames with the same name as the module names. If the argument isn't a directory, you get an error. This is great, for example, when you want to extract all the modules and drop them into some remote directory, like:

fhist -all -e -o tempdir

Also, be careful when you specify numeric edit numbers for multiple modules. Most probably a particular edit number isn't appropriate for multiple modules, since the changes corresponding to a particular edit number usually aren't related to each other. Using named edits avoids these problems entirely πŸ’…. Example: if you wanted to extract every module that had an edit named rev3, you'd do:

fhist -all -e rev3

Some other useful examples of commands which use multiple modules:

fhist *.c -create
fhist -check -all
fhist -cu -all
  • -Verbose β€” sprinkle this on with any other action and it outputs status information about the progress of the action. Great for debugging problems, or just for amusement when the system is slow or a large file is being processed πŸ“. It takes a numeric argument to indicate the verbosity of output. The levels are:
    • 0 β€” No output at all (except for errors).
    • 1 β€” Single‐line output describing action (default).
    • 2 β€” Detailed status as action proceeds.
  • -Help β€” gives you some help on how to use the fhist program. 🫢
  • -VERSion β€” shows what version of fhist is running.

✨ OPTIONS (the fine print, but make it cute) ✨

All options may be abbreviated; the abbreviation is documented as the upper case letters, and all lower case letters and underscores (_) are optional. You must use consecutive sequences of optional letters.

All options are case insensitive β€” type them upper case, lower case, or a mix, case is not important, periodt.

For example: the arguments -help, -HELP and -h are all interpreted to mean the -Help option. The argument -hlp will not be understood, because consecutive optional characters weren't supplied. 😭

Options and other command line arguments may be mixed arbitrarily on the command line.

The GNU long option names are understood. Since all option names for fhist are long, this means ignoring the extra leading -. The -option=value convention is also understood.


🌈 FILE NAME EXPANSION 🌈

As a convenience, if a pathname begins with a period and an environment variable exists with that name, then the value of the environment variable will be used as the actual pathname. For example, if an environment variable of .FOO has the value this.is.a.long.name, then the command

fhist -o .FOO

is actually equivalent to the command

fhist -o this.is.a.long.name

If you want to prevent the expansion of a pathname which begins with a period, then you can use an alternate form for the pathname, like:

fhist -o ./.FOO

πŸ¦‹ BINARY FILES πŸ¦‹

In general, fhist can handle all text files you throw at it β€” even international text with unusual encodings. Slay. However, fhist is unable to cope elegantly with files which contain the NUL character. 😬

The fcomp(1) program simply prints a warning and continues, but you need to know that it converts NUL characters into an 0x80 value before performing the comparison.

The fmerge(1) program also converts the NUL character to an 0x80 value before merging, after a warning, and any output file will contain this value, rather than the original NUL character.

The fhist(1) program, however, generates a fatal error if any input file contains NUL characters. This is intended to protect your source files from unintentional corruption. Use -BINary for files which absolutely must contain NUL characters.


πŸ’€ EXIT STATUS πŸ’€

The fhist program will exit with a status of 1 on any error. The fhist program will only exit with a status of 0 if there are no errors.


πŸ‘‘ REFERENCES πŸ‘‘

This program is based on the algorithm in

An O(ND) Difference Algorithm and Its Variations, Eugene W. Myers, TR 85‐6, 10‐April‐1985, Department of Computer Science, The University of Arizona, Tuscon, Arizona 85721.

See also:

A File Comparison Program, Webb Miller and Eugene W. Myers, Software Practice and Experience, Volume 15, No. 11, November 1985.

fhist version 1.21.D001

Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2012 Peter Miller;

This program is derived from a work Copyright (C) 1990 David I. Bell.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.


πŸ’– AUTHORS πŸ’–


And that's the whole page, bestie! 🫢 This lil' icon lives in the Reference Manual, filed under FHist, and it's the fhist(1) page for fhist version 1.21.D001. Go forth and version your files, you absolute main character πŸ’…βœ¨

πŸ“¦ where this page comes from