zsh_history
A tool (and Rust library) for merging zsh history files in zsh’s extended format.
One possible application is synchronization of shell histories across multiple machines in a decentralized way.
The extended format (see EXTENDED_HISTORY) is required so that zsh records timestamps together with the commands.
These timestamps are used for automatic robust conflict resolution.
Installation
cargo install --git https://git.grothesque.org/zsh_history
(Cargo is Rust’s package manager.)
Usage
zsh_history merge A B >MERGED
zsh_history merge A B ANCESTOR >MERGED
If the input files are valid zsh history files, the merged output will be also valid.
Conflicts are resolved automatically such that all history variants are preserved (A’s variant is output before B’s variant). The output contains all commands from A and B, with the exception of those commands that are clearly identified as deleted (by comparing with ANCESTOR) by one or both sides. If a command has been deleted by one side but modified by the other, the conflict is resolved by preserving the modified version.
The tool performs a single timestamp-synchronized pass through all inputs. At any timestamp value it considers at most one command from each input. Thus, if multiple consecutive commands have the same timestamp, and A and B differ, the merging will likely get out of sync, and detect spurious conflicts that will lead to commands being output twice (once for A and for B inputs). This is a theoretical problem that should almost never occur in practice.
The duration field is preserved but otherwise ignored.
Use with the Unison file synchronizer
The Unison file synchronizer can be configured to merge specific files using external tools when a conflict is detected. It can even keep ancestors around automatically. See the section “Merging Conflicting Versions” in the Unison manual.
