README
¶
= dof
image:https://img.shields.io/badge/License-Apache%202.0-blue.svg[link="http://www.apache.org/licenses/LICENSE-2.0"]
image:https://github.com/steffakasid/dof/actions/workflows/codeql-analysis.yml/badge.svg[link:https://github.com/steffakasid/dof/actions/workflows/codeql-analysis.yml]
image:https://github.com/steffakasid/dof/actions/workflows/release.yml/badge.svg[link:https://github.com/steffakasid/dof/actions/workflows/release.yml]
image:https://github.com/steffakasid/dof/actions/workflows/go-test.yml/badge.svg[link:https://github.com/steffakasid/dof/actions/workflows/go-test.yml]
dof is a CLI tool for managing dotfiles with a bare git repository. It maps a bare repository into a work tree and provides commands to initialize, checkout, add, synchronize, and manage dotfiles.
The tool is written in Go and uses `cobra` for CLI handling, `viper` for configuration, and `logrus` for logging.
== General usage
The typical workflow is:
* configure the repository path, branch, or profile.
* initialize or checkout the dotfile repository.
* add files with `dof add`.
* sync changes with `dof sync`.
* use `dof alias` for direct git commands when needed.
=== Initialize a new repository
When creating a new local dotfile repository:
* `dof init` - creates the bare repo and checks out the configured branch.
* `dof add <file>` - stages and commits a file into the dotfile repo.
* `dof alias remote add origin <git-url>` - add a remote repository.
* `dof sync` - push and pull changes on the configured branch.
If you use a remote repository, you may also need to set the upstream branch manually, for example:
[source,shell]
----
git config --global init.defaultBranch main
----
=== Checkout an existing repository
To connect to an existing remote dotfile repo:
* `dof checkout <git-remote-repo>` - clones the repo as a bare repository, renames existing local files as backups, and checks out the tracked dotfiles.
=== Synchronize changes
* `dof add <file>` - add and commit a file.
* `dof status` - show the git status for the current bare repository.
* `dof sync` - commit local changes, push to origin, and pull remote changes with rebase.
* `dof sync --push-only` - only commit and push local changes.
* `dof sync --pull-only` - only pull remote changes.
== Configuration
dof supports configuration in several ways:
* `--config <file>` or `-c` - use a custom config file.
* `--profile <name>` - select a named profile from the config.
* `--repository <path>` or `-r` - path to the bare git repository.
* `--branch <name>` or `-b` - git branch to track.
* environment variables prefixed with `DOF_`.
The default config file is `$HOME/.dof.yaml`.
Profiles are defined under `profiles.<name>` and can override `repository`, `branch`, `skip_files`, and `git_env`.
The `--profile` flag selects one named profile from this single config file. That means you can keep multiple repository definitions in one shared config and switch between them at runtime.
Example config:
[source,yaml]
----
repository: /home/user/.dof
branch: main
skip_files:
- README.md
- LICENSE
git_env:
GIT_CONFIG_GLOBAL: ~/.gitconfig
profiles:
work:
repository: /home/user/.dof-work
branch: work
skip_files:
- scm-info.yaml
- README.adoc
git_env:
GIT_CONFIG_GLOBAL: ~/.gitconfig_work
personal:
repository: /home/user/.dof-personal
branch: main
----
Use profiles like this:
* `dof --profile work init`
* `dof --profile personal sync`
=== Git environment variables
The `git_env` option is a map of environment variables that dof applies to
every git invocation (`init`, `checkout`, `add`, `sync`, `status`, `alias`).
Use it to control git's behaviour without changing your global git setup — for
example, to point git at a dedicated global config file:
[source,yaml]
----
git_env:
GIT_CONFIG_GLOBAL: ~/.gitconfig
GIT_SSH_COMMAND: ssh -i ~/.ssh/dof_key
----
Notes:
* `git_env` is configured only in the config file (globally and per profile);
there is no CLI flag or `DOF_` environment variable for it.
* Profile values win over global values per key; keys set only globally are
merged in.
* The variables are added on top of your existing shell environment — you only
list additions or overrides; `PATH`, `HOME`, and the rest are kept.
* Values are passed to git verbatim; dof does not expand `~` or `$VAR`
(git itself expands `~` in paths such as `GIT_CONFIG_GLOBAL`).
=== Adding a profile
To add a new profile, open `$HOME/.dof.yaml` and add an entry under `profiles`:
[source,yaml]
----
profiles:
myprofile:
repository: /home/user/.dof-myprofile
branch: main
skip_files:
- README.md
----
Each profile can set any combination of `repository`, `branch`, and `skip_files`. Values you omit fall back to the top-level defaults.
Then use the profile with `--profile myprofile`:
[source,shell]
----
dof --profile myprofile init
dof --profile myprofile checkout git@github.com:user/dotfiles.git
dof --profile myprofile sync
----
=== Skipping files
Some dotfile repositories contain files that are useful on the remote (e.g. `README.md`, `LICENSE`, `scm-info.yaml`) but should not appear in the home directory. The `skip_files` option excludes these files from the working tree.
Add the files you want to skip to your config:
[source,yaml]
----
skip_files:
- README.md
- README.adoc
- LICENSE
- scm-info.yaml
----
This works by setting up git sparse-checkout in non-cone mode. Once applied, the excluded files stay absent across all git operations (checkout, pull, merge) without any extra wrapper logic.
The skip rules are applied automatically when you run `dof init` or `dof checkout`. If you change the `skip_files` list later, run `dof init` again to update the sparse-checkout rules.
To add `skip_files` to an existing repository that was already initialized, just add the list to your `$HOME/.dof.yaml` and run:
[source,shell]
----
dof init
----
This re-applies the sparse-checkout rules and removes the skipped files from your working tree. The files remain tracked in git and are still pushed to the remote — they just do not appear locally.
== Command overview
* `dof init` - initialize a bare dotfile repository.
* `dof checkout <git-repo-url>` - clone and checkout an existing bare repository.
* `dof add <file>` - add a file to the repository and commit it.
* `dof status` - show repository status.
* `dof sync` - sync local and remote changes.
* `dof alias ...` - run any git command against the configured bare repository.
* `dof completion <bash|zsh|fish|powershell>` - generate shell completion.
* `dof version` - print version and build metadata.
== Project structure
* `main.go` - application entrypoint.
* `cmd/` - CLI command implementations.
** `root.go` - root command, configuration and flags.
** `init.go` - repository initialization logic.
** `checkout.go` - checkout workflow for existing repos.
** `add.go` - add files to the repository.
** `sync.go` - sync workflow with remote.
** `status.go` - git status command.
** `alias.go` - arbitrary git command support.
** `completion.go` - shell completion generation.
** `version.go` - version command.
* `go.mod`, `go.sum` - module and dependency definitions.
== Dependencies
dof requires `git` to be installed and available on `PATH`.
Go dependencies:
* `github.com/spf13/cobra` - CLI command framework.
* `github.com/spf13/viper` - configuration and environment handling.
* `github.com/sirupsen/logrus` - logging.
* `github.com/stretchr/testify` - unit testing helpers.
Indirect dependencies include the Cobra/Viper ecosystem packages such as `fsnotify`, `pflag`, `afero`, and `yaml.v3`.
== Development
Build the project:
[source,shell]
----
go build -o dof ./...
----
Run the CLI:
[source,shell]
----
./dof --help
go run main.go --help
----
Run tests:
[source,shell]
----
go test ./...
----
Format the code:
[source,shell]
----
go fmt ./...
----
== Notes
dof is designed to work with one configured repository per invocation. Use profiles, `--repository`, or `--config` to switch between repositories on the same machine.
== GitHub Actions
This repository uses GitHub Actions for continuous integration, including Go tests, CodeQL analysis, and release workflow automation. It also builds binaries for release distribution.
Documentation
¶
Overview ¶
Copyright © 2020 Steffen Rumpf <github@steffen-rumpf.de>
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Click to show internal directories.
Click to hide internal directories.