Full Code of sobolevn/git-secret for AI

master b9b771b64a6c cached
380 files
689.9 KB
227.7k tokens
1 symbols
1 requests
Download .txt
Showing preview only (779K chars total). Download the full file or copy to clipboard to get everything.
Repository: sobolevn/git-secret
Branch: master
Commit: b9b771b64a6c
Files: 380
Total size: 689.9 KB

Directory structure:
gitextract_322qge9w/

├── .ci/
│   ├── docker-ci/
│   │   ├── alma/
│   │   │   └── Dockerfile
│   │   ├── alpine/
│   │   │   └── Dockerfile
│   │   ├── arch/
│   │   │   └── Dockerfile
│   │   ├── debian-gnupg1/
│   │   │   └── Dockerfile
│   │   ├── debian-gnupg2/
│   │   │   └── Dockerfile
│   │   ├── fedora/
│   │   │   └── Dockerfile
│   │   ├── rocky/
│   │   │   └── Dockerfile
│   │   └── ubuntu/
│   │       └── Dockerfile
│   ├── github_release_script.sh
│   ├── release-ci/
│   │   ├── alma/
│   │   │   └── Dockerfile
│   │   ├── alpine/
│   │   │   └── Dockerfile
│   │   ├── debian/
│   │   │   └── Dockerfile
│   │   ├── fedora/
│   │   │   └── Dockerfile
│   │   ├── rocky/
│   │   │   └── Dockerfile
│   │   └── ubuntu/
│   │       └── Dockerfile
│   └── releaser/
│       └── alpine/
│           └── Dockerfile
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── build-man.yml
│       ├── github-pages.yml
│       ├── release-ci.yml
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── Makefile
├── README.md
├── RFC/
│   └── RFC001.md
├── docs/
│   ├── Gemfile
│   ├── _config.yml
│   ├── _includes/
│   │   ├── favicons.html
│   │   ├── footer.html
│   │   ├── head.html
│   │   ├── header.html
│   │   ├── icon-github.html
│   │   ├── icon-twitter.html
│   │   └── why.md
│   ├── _layouts/
│   │   ├── default.html
│   │   ├── page.html
│   │   └── post.html
│   ├── _sass/
│   │   ├── _base.scss
│   │   ├── _layout.scss
│   │   └── _syntax-highlighting.scss
│   ├── build.sh
│   ├── css/
│   │   └── main.scss
│   ├── feed.xml
│   ├── images/
│   │   └── favicons/
│   │       ├── browserconfig.xml
│   │       └── manifest.json
│   ├── index.html
│   ├── installation.md
│   └── plugins.md
├── man/
│   ├── man1/
│   │   ├── git-secret-add.1
│   │   ├── git-secret-add.1.md
│   │   ├── git-secret-cat.1
│   │   ├── git-secret-cat.1.md
│   │   ├── git-secret-changes.1
│   │   ├── git-secret-changes.1.md
│   │   ├── git-secret-clean.1
│   │   ├── git-secret-clean.1.md
│   │   ├── git-secret-hide.1
│   │   ├── git-secret-hide.1.md
│   │   ├── git-secret-init.1
│   │   ├── git-secret-init.1.md
│   │   ├── git-secret-list.1
│   │   ├── git-secret-list.1.md
│   │   ├── git-secret-remove.1
│   │   ├── git-secret-remove.1.md
│   │   ├── git-secret-removeperson.1
│   │   ├── git-secret-removeperson.1.md
│   │   ├── git-secret-reveal.1
│   │   ├── git-secret-reveal.1.md
│   │   ├── git-secret-tell.1
│   │   ├── git-secret-tell.1.md
│   │   ├── git-secret-usage.1
│   │   ├── git-secret-usage.1.md
│   │   ├── git-secret-whoknows.1
│   │   └── git-secret-whoknows.1.md
│   └── man7/
│       ├── git-secret.7
│       └── git-secret.7.md
├── src/
│   ├── _utils/
│   │   ├── _git_secret_tools.sh
│   │   ├── _git_secret_tools_freebsd.sh
│   │   ├── _git_secret_tools_linux.sh
│   │   └── _git_secret_tools_osx.sh
│   ├── commands/
│   │   ├── git_secret_add.sh
│   │   ├── git_secret_cat.sh
│   │   ├── git_secret_changes.sh
│   │   ├── git_secret_clean.sh
│   │   ├── git_secret_hide.sh
│   │   ├── git_secret_init.sh
│   │   ├── git_secret_list.sh
│   │   ├── git_secret_remove.sh
│   │   ├── git_secret_removeperson.sh
│   │   ├── git_secret_reveal.sh
│   │   ├── git_secret_tell.sh
│   │   ├── git_secret_usage.sh
│   │   └── git_secret_whoknows.sh
│   ├── main.sh
│   └── version.sh
├── tests/
│   ├── _test_base.bash
│   ├── fixtures/
│   │   └── gpg/
│   │       ├── README.md
│   │       ├── attacker1@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user1@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user2@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user3@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user4@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       └── user5@gitsecret.io/
│   │           ├── private.key
│   │           └── public.key
│   ├── test_add.bats
│   ├── test_cat.bats
│   ├── test_changes.bats
│   ├── test_clean.bats
│   ├── test_expiration.bats
│   ├── test_hide.bats
│   ├── test_hide_continue.bats
│   ├── test_init.bats
│   ├── test_list.bats
│   ├── test_main.bats
│   ├── test_make_install.bats
│   ├── test_noname.bats
│   ├── test_remove.bats
│   ├── test_removeperson.bats
│   ├── test_reveal.bats
│   ├── test_reveal_filename.bats
│   ├── test_tell.bats
│   ├── test_usage.bats
│   └── test_whoknows.bats
├── utils/
│   ├── apk/
│   │   ├── build.sh
│   │   ├── deploy.sh
│   │   ├── install.sh
│   │   ├── meta.sh
│   │   └── nfpm.yml
│   ├── build-utils.sh
│   ├── deb/
│   │   ├── build.sh
│   │   ├── deploy.sh
│   │   └── install.sh
│   ├── install.sh
│   ├── rpm/
│   │   ├── build.sh
│   │   ├── deploy.sh
│   │   ├── git-secret.repo
│   │   └── install.sh
│   ├── tests.sh
│   └── uninstall.sh
└── vendor/
    ├── README.md
    └── bats-core/
        ├── .devcontainer/
        │   ├── Dockerfile
        │   └── devcontainer.json
        ├── .editorconfig
        ├── .gitattributes
        ├── .github/
        │   ├── ISSUE_TEMPLATE/
        │   │   ├── bug_report.md
        │   │   └── feature_request.md
        │   └── workflows/
        │       ├── check_pr_label.sh
        │       ├── release.yml
        │       ├── release_dockerhub.yml
        │       └── tests.yml
        ├── .gitignore
        ├── .readthedocs.yml
        ├── AUTHORS
        ├── Dockerfile
        ├── LICENSE.md
        ├── README.md
        ├── bin/
        │   └── bats
        ├── contrib/
        │   ├── release.sh
        │   ├── rpm/
        │   │   └── bats.spec
        │   └── semver
        ├── docker/
        │   ├── install_tini.sh
        │   └── tini.pubkey.gpg
        ├── docker-compose.override.dist
        ├── docker-compose.yml
        ├── docs/
        │   ├── .markdownlint.json
        │   ├── CHANGELOG.md
        │   ├── CODEOWNERS
        │   ├── CODE_OF_CONDUCT.md
        │   ├── CONTRIBUTING.md
        │   ├── Makefile
        │   ├── PULL_REQUEST_TEMPLATE.md
        │   ├── examples/
        │   │   ├── README.md
        │   │   ├── package-tarball
        │   │   └── package-tarball.bats
        │   ├── make.bat
        │   ├── releasing.md
        │   ├── source/
        │   │   ├── _static/
        │   │   │   └── .gitkeep
        │   │   ├── _templates/
        │   │   │   └── .gitkeep
        │   │   ├── conf.py
        │   │   ├── docker-usage.md
        │   │   ├── faq.rst
        │   │   ├── gotchas.rst
        │   │   ├── index.rst
        │   │   ├── installation.rst
        │   │   ├── requirements.txt
        │   │   ├── tutorial.rst
        │   │   ├── usage.md
        │   │   └── writing-tests.md
        │   └── versions.md
        ├── install.sh
        ├── lib/
        │   └── bats-core/
        │       ├── common.bash
        │       ├── formatter.bash
        │       ├── preprocessing.bash
        │       ├── semaphore.bash
        │       ├── test_functions.bash
        │       ├── tracing.bash
        │       └── validator.bash
        ├── libexec/
        │   └── bats-core/
        │       ├── bats
        │       ├── bats-exec-file
        │       ├── bats-exec-suite
        │       ├── bats-exec-test
        │       ├── bats-format-cat
        │       ├── bats-format-junit
        │       ├── bats-format-pretty
        │       ├── bats-format-tap
        │       ├── bats-format-tap13
        │       └── bats-preprocess
        ├── man/
        │   ├── Makefile
        │   ├── README.md
        │   ├── bats.1
        │   ├── bats.1.ronn
        │   ├── bats.7
        │   └── bats.7.ronn
        ├── package.json
        ├── shellcheck.sh
        ├── test/
        │   ├── bats.bats
        │   ├── concurrent-coordination.bash
        │   ├── file_setup_teardown.bats
        │   ├── fixtures/
        │   │   ├── bats/
        │   │   │   ├── BATS_TMPDIR.bats
        │   │   │   ├── cmd_using_stdin.bash
        │   │   │   ├── comment_style.bats
        │   │   │   ├── dos_line_no_shellcheck.bats
        │   │   │   ├── duplicate-tests_no_shellcheck.bats
        │   │   │   ├── empty.bats
        │   │   │   ├── environment.bats
        │   │   │   ├── evaluation_count/
        │   │   │   │   ├── file1.bats
        │   │   │   │   └── file2.bats
        │   │   │   ├── expand_var_in_test_name.bats
        │   │   │   ├── exported_function.bats
        │   │   │   ├── external_function_calls.bats
        │   │   │   ├── external_functions.bash
        │   │   │   ├── external_functions.bats
        │   │   │   ├── failing.bats
        │   │   │   ├── failing_and_passing.bats
        │   │   │   ├── failing_helper.bats
        │   │   │   ├── failing_setup.bats
        │   │   │   ├── failing_teardown.bats
        │   │   │   ├── failing_with_bash_cond.bats
        │   │   │   ├── failing_with_bash_expression.bats
        │   │   │   ├── failing_with_negated_command.bats
        │   │   │   ├── failure_in_free_code.bats
        │   │   │   ├── hang_after_run.bats
        │   │   │   ├── hang_in_run.bats
        │   │   │   ├── hang_in_setup_file.bats
        │   │   │   ├── hang_in_teardown.bats
        │   │   │   ├── hang_in_teardown_file.bats
        │   │   │   ├── hang_in_test.bats
        │   │   │   ├── intact.bats
        │   │   │   ├── issue-205.bats
        │   │   │   ├── issue-433/
        │   │   │   │   ├── repro1.bats
        │   │   │   │   └── repro2.bats
        │   │   │   ├── issue-519.bats
        │   │   │   ├── load.bats
        │   │   │   ├── loop_keep_IFS.bats
        │   │   │   ├── no-final-newline.bats
        │   │   │   ├── output.bats
        │   │   │   ├── parallel.bats
        │   │   │   ├── passing.bats
        │   │   │   ├── passing_and_failing.bats
        │   │   │   ├── passing_and_skipping.bats
        │   │   │   ├── passing_failing_and_skipping.bats
        │   │   │   ├── print_output_on_failure.bats
        │   │   │   ├── quoted_and_unquoted_test_names_no_shellcheck.bats
        │   │   │   ├── read_from_stdin.bats
        │   │   │   ├── reference_unset_parameter.bats
        │   │   │   ├── reference_unset_parameter_in_setup.bats
        │   │   │   ├── reference_unset_parameter_in_teardown.bats
        │   │   │   ├── run_long_command.bats
        │   │   │   ├── set_-eu_in_setup_and_teardown.bats
        │   │   │   ├── setup.bats
        │   │   │   ├── show-output-of-passing-tests.bats
        │   │   │   ├── single_line_no_shellcheck.bats
        │   │   │   ├── skipped.bats
        │   │   │   ├── skipped_with_parens.bats
        │   │   │   ├── source_nonexistent_file.bats
        │   │   │   ├── source_nonexistent_file_in_setup.bats
        │   │   │   ├── source_nonexistent_file_in_teardown.bats
        │   │   │   ├── tab in filename.bats
        │   │   │   ├── teardown.bats
        │   │   │   ├── test_helper.bash
        │   │   │   ├── unbound_variable.bats
        │   │   │   ├── unofficial_bash_strict_mode.bash
        │   │   │   ├── unofficial_bash_strict_mode.bats
        │   │   │   ├── update_path_env.bats
        │   │   │   ├── verbose-run.bats
        │   │   │   ├── whitespace_no_shellcheck.bats
        │   │   │   └── without_trailing_newline.bats
        │   │   ├── file_setup_teardown/
        │   │   │   ├── no_setup_file.bats
        │   │   │   ├── no_teardown_file.bats
        │   │   │   ├── setup_file.bats
        │   │   │   ├── setup_file2.bats
        │   │   │   ├── setup_file_does_not_leak_env.bats
        │   │   │   ├── setup_file_does_not_leak_env2.bats
        │   │   │   ├── setup_file_even_if_all_tests_are_skipped.bats
        │   │   │   ├── setup_file_failed.bats
        │   │   │   ├── setup_file_halfway_error.bats
        │   │   │   ├── teardown_file.bats
        │   │   │   ├── teardown_file2.bats
        │   │   │   ├── teardown_file_after_failing_test.bats
        │   │   │   ├── teardown_file_after_long_test.bats
        │   │   │   ├── teardown_file_does_not_leak.bats
        │   │   │   ├── teardown_file_does_not_leak2.bats
        │   │   │   ├── teardown_file_even_if_all_tests_are_skipped.bats
        │   │   │   ├── teardown_file_failed.bats
        │   │   │   └── teardown_file_halfway_error.bats
        │   │   ├── junit-formatter/
        │   │   │   ├── duplicate/
        │   │   │   │   ├── first/
        │   │   │   │   │   └── file1.bats
        │   │   │   │   └── second/
        │   │   │   │       └── file1.bats
        │   │   │   ├── issue_360.bats
        │   │   │   ├── issue_531.bats
        │   │   │   ├── skipped.bats
        │   │   │   ├── suite/
        │   │   │   │   ├── file1.bats
        │   │   │   │   └── file2.bats
        │   │   │   └── xml-escape.bats
        │   │   ├── load/
        │   │   │   ├── ambiguous
        │   │   │   ├── ambiguous.bash
        │   │   │   ├── bats_load_library.bats
        │   │   │   ├── exit1.bash
        │   │   │   ├── failing_bats_load_library.bats
        │   │   │   ├── failing_load.bats
        │   │   │   ├── find_library_helper.bats
        │   │   │   ├── find_library_helper_err.bats
        │   │   │   ├── load.bats
        │   │   │   ├── return1.bash
        │   │   │   └── test_helper.bash
        │   │   ├── parallel/
        │   │   │   ├── must_not_parallelize_across_files/
        │   │   │   │   ├── file1.bats
        │   │   │   │   └── file2.bats
        │   │   │   ├── must_not_parallelize_within_file.bats
        │   │   │   ├── parallel-preserve-environment.bats
        │   │   │   ├── parallel.bats
        │   │   │   ├── parallel_factor.bats
        │   │   │   ├── setup_file/
        │   │   │   │   └── setup_file.bats
        │   │   │   └── suite/
        │   │   │       └── parallel1.bats
        │   │   ├── run/
        │   │   │   ├── failing.bats
        │   │   │   └── invalid.bats
        │   │   ├── suite/
        │   │   │   ├── empty/
        │   │   │   │   └── .gitkeep
        │   │   │   ├── filter/
        │   │   │   │   ├── a.bats
        │   │   │   │   ├── b.bats
        │   │   │   │   └── c.bats
        │   │   │   ├── multiple/
        │   │   │   │   ├── a.bats
        │   │   │   │   └── b.bats
        │   │   │   ├── override_BATS_FILE_EXTENSION/
        │   │   │   │   ├── subfolder/
        │   │   │   │   │   └── test.other_extension
        │   │   │   │   ├── test.bats
        │   │   │   │   └── test.test
        │   │   │   ├── recursive/
        │   │   │   │   ├── subsuite/
        │   │   │   │   │   └── test2.bats
        │   │   │   │   └── test.bats
        │   │   │   ├── single/
        │   │   │   │   └── test.bats
        │   │   │   ├── skip/
        │   │   │   │   ├── skip-in-setup-and-teardown.bats
        │   │   │   │   ├── skip-in-setup.bats
        │   │   │   │   ├── skip-in-teardown.bats
        │   │   │   │   ├── skip-in-test-and-teardown.bats
        │   │   │   │   └── skip-in-test.bats
        │   │   │   └── test_number/
        │   │   │       ├── file1.bats
        │   │   │       └── file2.bats
        │   │   └── trace/
        │   │       ├── failing_complex.bats
        │   │       └── failing_recursive.bats
        │   ├── install.bats
        │   ├── junit-formatter.bats
        │   ├── load.bats
        │   ├── parallel.bats
        │   ├── pretty-formatter.bats
        │   ├── root.bats
        │   ├── run.bats
        │   ├── suite.bats
        │   ├── test_helper.bash
        │   └── trace.bats
        └── uninstall.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .ci/docker-ci/alma/Dockerfile
================================================
FROM almalinux:8

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN dnf -y update \
  && dnf install -y \
    # Direct dependencies:
    bash \
    gawk \
    git \
    gnupg \
    # Assumed to be present:
    diffutils \
    file \
    findutils \
    procps \
    make \
  && dnf clean all \
  && rm -rf /var/cache/yum


================================================
FILE: .ci/docker-ci/alpine/Dockerfile
================================================
FROM alpine:3.23.3

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

# Don't install coreutils on Alpine,
# so we get busybox versions of ps, stat, and ls. See #475
RUN apk add --no-cache --update \
  # Direct dependencies:
  bash \
  gawk \
  git \
  gnupg \
  # Assumed to be present:
  file \
  make \
  procps


================================================
FILE: .ci/docker-ci/arch/Dockerfile
================================================
FROM archlinux:base-20220529.0.58327

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN pacman -Syu --needed --noconfirm \
  # Direct dependencies:
  bash \
  gawk \
  git \
  gnupg \
  # Assumed to be present:
  diffutils \
  file \
  make \
  procps



================================================
FILE: .ci/docker-ci/debian-gnupg1/Dockerfile
================================================
FROM debian:13.3-slim

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

ENV DEBIAN_FRONTEND='noninteractive'
ENV SECRETS_GPG_COMMAND='gpg1'

RUN apt-get update \
  && apt-get install --no-install-recommends -y \
    # Direct dependencies:
    gawk \
    git \
    gnupg1 \
    # Assumed to be present:
    file \
    procps \
    make \
  # Cleaning cache:
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && apt-get clean -y && rm -rf /var/lib/apt/lists/*


================================================
FILE: .ci/docker-ci/debian-gnupg2/Dockerfile
================================================
FROM debian:13.3-slim

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

ENV DEBIAN_FRONTEND='noninteractive'

RUN apt-get update \
  && apt-get install --no-install-recommends -y \
    # Direct dependencies:
    gawk \
    git \
    gnupg \
    # Assumed to be present:
    file \
    procps \
    make \
  # Cleaning cache:
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && apt-get clean -y && rm -rf /var/lib/apt/lists/*


================================================
FILE: .ci/docker-ci/fedora/Dockerfile
================================================
FROM fedora:43

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN dnf -y update \
  && dnf install -y \
    # Direct dependencies:
    bash \
    gawk \
    git \
    gnupg \
    # Assumed to be present:
    diffutils \
    file \
    findutils \
    procps \
    make \
  && dnf clean all \
  && rm -rf /var/cache/yum


================================================
FILE: .ci/docker-ci/rocky/Dockerfile
================================================
FROM rockylinux:8

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN dnf -y update \
  && dnf install -y \
    # Direct dependencies:
    bash \
    gawk \
    git \
    gnupg \
    # Assumed to be present:
    diffutils \
    file \
    findutils \
    procps \
    make \
  && dnf clean all \
  && rm -rf /var/cache/yum


================================================
FILE: .ci/docker-ci/ubuntu/Dockerfile
================================================
FROM ubuntu:24.04

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

ENV DEBIAN_FRONTEND="noninteractive"

RUN apt-get update \
  && apt-get install --no-install-recommends -y \
    # Direct dependencies:
    gawk \
    git \
    gnupg \
    # Assumed to be present:
    file \
    procps \
    make \
  # Cleaning cache:
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && apt-get clean -y && rm -rf /var/lib/apt/lists/*


================================================
FILE: .ci/github_release_script.sh
================================================
#!/usr/bin/env sh

set -e

# Installing additional deps:
apk add --no-cache curl jq

# https://gist.github.com/Jaskaranbir/d5b065173b3a6f164e47a542472168c1
USER="$(echo "$GITHUB_REPOSITORY" | cut -d "/" -f1)"
PROJECT="$(echo "$GITHUB_REPOSITORY" | cut -d "/" -f2)"

LAST_RELEASE_TAG=$(curl \
    --header "authorization: Bearer $GITHUB_TOKEN" \
    --url "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest" \
  | jq .tag_name | sed 's/"//g'
)
echo "LAST_RELEASE_TAG=$LAST_RELEASE_TAG"
if [ "$LAST_RELEASE_TAG" = 'null' ]; then
  # Most likely, we are facing rate-limiting problems,
  # just try again later.
  exit 1
fi

NEW_CHANGELOG='CHANGELOG-RELEASE.md'

# Generate new CHANGELOG.md with just the last changes
github_changelog_generator \
  --user "$USER" \
  --project "$PROJECT" \
  --token "$GITHUB_OAUTH_TOKEN" \
  --since-tag "$LAST_RELEASE_TAG" \
  --max-issues 100 \
  --no-issues \
  --release-branch 'master' \
  --token "$GITHUB_TOKEN" \
  --output "$NEW_CHANGELOG"

echo 'Done! Changelog:'
cat "$NEW_CHANGELOG"


================================================
FILE: .ci/release-ci/alma/Dockerfile
================================================
FROM almalinux:8

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN dnf -y update \
  && dnf install -y \
    # Required for our install script:
    wget \
    sudo \
  && dnf clean all \
  && rm -rf /var/cache/yum


================================================
FILE: .ci/release-ci/alpine/Dockerfile
================================================
FROM alpine:3.23.3

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN apk add --no-cache --update \
  # Required for our install script:
  bash \
  wget


================================================
FILE: .ci/release-ci/debian/Dockerfile
================================================
FROM debian:13.3-slim

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

ENV DEBIAN_FRONTEND='noninteractive'

RUN apt-get update \
  && apt-get install --no-install-recommends -y \
    # Required to work with https-based repos and custom signed packages:
    apt-transport-https \
    ca-certificates \
    # Required for our install script:
    gnupg \
    sudo \
    wget \
  # Cleaning cache:
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
  && adduser --disabled-password nonroot \
  && adduser nonroot sudo \
  && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER nonroot


================================================
FILE: .ci/release-ci/fedora/Dockerfile
================================================
FROM fedora:43

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN dnf -y update \
  && dnf install -y \
    # Required for our install script:
    wget \
    sudo \
  && dnf clean all \
  && rm -rf /var/cache/yum \
  && adduser --password='' -m nonroot \
  && echo 'nonroot ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER nonroot
WORKDIR /home/nonroot


================================================
FILE: .ci/release-ci/rocky/Dockerfile
================================================
FROM rockylinux:8

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

RUN dnf -y update \
  && dnf install -y \
    # Required for our install script:
    wget \
    sudo \
  && dnf clean all \
  && rm -rf /var/cache/yum


================================================
FILE: .ci/release-ci/ubuntu/Dockerfile
================================================
FROM ubuntu:24.04

LABEL maintainer="mail@sobolevn.me"
LABEL vendor="git-secret team"

ENV DEBIAN_FRONTEND='noninteractive'

RUN apt-get update \
  && apt-get install --no-install-recommends -y \
    # Required to work with https-based repos and custom signed packages:
    apt-transport-https \
    ca-certificates \
    # Required for our install script:
    gnupg \
    sudo \
    wget \
  # Cleaning cache:
  && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
  && apt-get clean -y && rm -rf /var/lib/apt/lists/* \
  && adduser --disabled-password nonroot \
  && adduser nonroot sudo \
  && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER nonroot


================================================
FILE: .ci/releaser/alpine/Dockerfile
================================================
# Initially copied from
# https://github.com/jordansissel/fpm/blob/master/Dockerfile
FROM alpine:3.23.3

SHELL ["/bin/ash", "-eo", "pipefail", "-c"]

ENV CODE_DIR='/code'
ENV SECRETS_PROJECT_ROOT="$CODE_DIR"
ENV NFPM_VERSION='2.15.1'

RUN apk add --no-cache --update \
    # fpm deps:
    ruby \
    ruby-dev \
    gcc \
    libffi-dev \
    make \
    libc-dev \
    rpm \
    tar \
    # Direct dependencies:
    bash \
    gawk \
    git \
    gnupg \
    # Assumed to be present:
    curl \
    # envsubst for `nfpm`:
    gettext \
  # Installing `nfpm`, it builds alpine packages:
  && curl -sfL "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_x86_64.tar.gz" --output 'nfpm.tar.gz' \
  && tar -xf 'nfpm.tar.gz' nfpm \
  && mv nfpm '/usr/local/bin' \
  && chmod 755 '/usr/local/bin/nfpm' \
  && rm -rf 'nfpm.tar.gz' \
  # Installing `fpm`, it builds all other packages:
  && gem install --no-document fpm

WORKDIR $CODE_DIR


================================================
FILE: .editorconfig
================================================
# Check http://editorconfig.org for more information
# This is the main config file for this project:
root = true

[*]
charset = utf-8
indent_style = space
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
indent_size = 2

[Makefile]
indent_style = tab
indent_size = 4


================================================
FILE: .gitattributes
================================================
# Excluding from GitHub languages:
vendor/ linguist-vendored

# Excluding from GitHub diff:
*.1 linguist-generated
*.7 linguist-generated

# Excluding from `git diff`:
*.1 -diff
*.7 -diff


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: wemake-services
open_collective: git-secret
custom: https://boosty.to/sobolevn


================================================
FILE: .github/ISSUE_TEMPLATE.md
================================================
<!-- Thanks for reporting an issue! Please make sure you click the link above to view the issue guidelines, then fill out the blanks below. -->

What are the steps to reproduce this issue?
-------------------------------------------
1. …
2. …
3. …

What happens?
-------------
…

What were you expecting to happen?
----------------------------------
…

Any logs, error output, etc?
----------------------------
(If it’s long, please paste to https://ghostbin.com/ and insert the link here.)

Any other comments?
-------------------
…

What versions of software are you using?
----------------------------------------
**Operating system:** (`uname -a`) …

**`git-secret` path:** (`which git-secret`) …

**`git-secret` version:** (`git secret --version`) …

**`git` version:** (`git --version`) …

**Shell type and version:** (`$SHELL --version`) …

**`gpg` version:** (`gpg --version`) …

<!-- Love git-secret? Please consider supporting our collective:
👉  https://opencollective.com/git-secret/donate -->


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!-- Thanks for sending a pull request!

Here's how it's done:
0. If you are planning a large feature, please, discuss it first in a separate issue.
   See also [CONTRIBUTING.md](https://github.com/sobolevn/git-secret/blob/master/CONTRIBUTING.md) if you haven't already.
1. Make sure that you open your pull request against the `master` branch
2. Make sure that your code has the same style as the surrounding code and git-secret in general
3. Make sure your code passes using `shellcheck` with `make lint`
4. You can also spell check your code using 'aspell -c {filename}'
5. If you are adding or changing features, please add tests that cover the new behavior (in addition to the unchanged behavior if appropriate)
6. Make sure that all tests pass
7. Change the .md file(s) in man/man*/ to document your changes if appropriate
   (regenerating man pages with 'make build-man' is optional)
8. Add an entry to CHANGELOG.md explaining the change briefly and, if appropriate, referring to the related issue #

Please make sure you click the link above to view the contribution guidelines, then fill out the blanks below. -->

What does this implement/fix? Explain your changes.
---------------------------------------------------
…

Does this close any currently open issues?
------------------------------------------
…

Any relevant logs, error output, etc?
-------------------------------------
(If it’s long, please paste to https://ghostbin.com/ and insert the link here.)

Any other comments?
-------------------
…


================================================
FILE: .github/dependabot.yml
================================================
# GitHub-native dependabot setup, configuration:
# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates
version: 2

updates:

# Docs and GitHub Actions:

- package-ecosystem: bundler
  directory: "/docs"
  schedule:
    interval: daily

- package-ecosystem: github-actions
  directory: "/"
  schedule:
    interval: daily

# Our CI and release docker images:

- package-ecosystem: docker
  directory: ".ci/releaser/alpine"
  schedule:
    interval: weekly

# Release CI:

- package-ecosystem: docker
  directory: ".ci/release-ci/alpine"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/release-ci/debian"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/release-ci/ubuntu"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/release-ci/centos"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/release-ci/fedora"
  schedule:
    interval: weekly

# Docker CI:

- package-ecosystem: docker
  directory: ".ci/docker-ci/alpine"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/docker-ci/debian-gnupg1"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/docker-ci/debian-gnupg2"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/docker-ci/ubuntu"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/docker-ci/centos"
  schedule:
    interval: weekly

- package-ecosystem: docker
  directory: ".ci/docker-ci/fedora"
  schedule:
    interval: weekly


================================================
FILE: .github/workflows/build-man.yml
================================================

name: build-man

on:
  push:
    branches:
      - master
    paths:
      - 'docs/**/*'
      - '.github/workflows/build-man.yml'
  pull_request:
    paths:
      - 'docs/**/*'
      - '.github/workflows/build-man.yml'
  workflow_dispatch:

concurrency: 
  group: ${{ github.head_ref || github.run_id }}-build-man
  cancel-in-progress: true

jobs:
  build-man:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - name: Checks that manual generation works
      run: make build-man


================================================
FILE: .github/workflows/github-pages.yml
================================================
name: github-pages

on:
  push:
    branches:
      - master
    paths:
      - 'man/**/*'
      - 'docs/**/*'
      - 'utils/*/install.sh'

concurrency: 
  group: ${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v6

    - name: Build docs
      run: make build-docs

    - name: Deploy to Pages
      uses: JamesIves/github-pages-deploy-action@v4.8.0
      with:
        token: ${{ secrets.GITHUB_TOKEN }}
        branch: gh-pages # The branch the action should deploy to.
        folder: docs # The folder the action should deploy.
        clean: true # Automatically remove deleted files from the deploy branch


================================================
FILE: .github/workflows/release-ci.yml
================================================
name: release-ci

on:
  workflow_dispatch:
  schedule:
    - cron: '0 0 * * *'

  # In case we change the some build scripts:
  push:
    branches:
      - master
    paths:
      - 'utils/**'
      - '.ci/release-ci/**'
      - 'Makefile'
      - '.github/workflows/release-ci.yml'
  pull_request:
    paths:
      - 'utils/**'
      - '.ci/release-ci/**'
      - 'Makefile'
      - '.github/workflows/release-ci.yml'

concurrency:
  group: ${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  existing:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - release-type: deb
            release-env: debian
          - release-type: deb
            release-env: ubuntu
          - release-type: rpm
            release-env: fedora
          - release-type: rpm
            release-env: rocky
          - release-type: rpm
            release-env: alma
          - release-type: apk
            release-env: alpine

    steps:
    - uses: actions/checkout@v6
    - name: Run checks
      run: |
        SECRETS_RELEASE_ENV="${{ matrix.release-env }}" \
        SECRETS_RELEASE_TYPE="${{ matrix.release-type }}" \
        make release-ci

  # Keep in sync with `release.yml`:
  dryrun:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        release-type:
          - apk
          - deb
          - rpm
    steps:
    - uses: actions/checkout@v6
    - name: Run dry run of the release process
      run: |
        SECRETS_RELEASE_TYPE="${{ matrix.release-type }}" \
        SECRETS_DEPLOY_DRY_RUN=1 \
        SECRETS_ARTIFACTORY_CREDENTIALS='fake' \
          make release

  # https://github.community/t/run-github-actions-job-only-if-previous-job-has-failed/174786/2
  create-issue-on-failure:
    name: Create an issue if release-ci cron failed
    runs-on: ubuntu-latest
    needs: [existing, dryrun]
    if: ${{ github.event_name == 'schedule' && github.repository == 'sobolevn/git-secret' && always() && (needs.existing.result == 'failure' || needs.dryrun.result == 'failure') }}
    permissions:
      issues: write
    steps:
      - uses: actions/github-script@v8
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            await github.rest.issues.create({
              owner: "sobolevn",
              repo: "git-secret",
              title: `release-ci failure on ${new Date().toDateString()}`,
              body: "Details: https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml",
            })


================================================
FILE: .github/workflows/release.yml
================================================
name: release

on:
  push:
    tags:
      - 'v*'
  workflow_dispatch:

concurrency:
  group: ${{ github.head_ref || github.run_id }}

jobs:
  release-packages:
    environment:
      name: artifactory
      url: https://gitsecret.jfrog.io/artifactory

    runs-on: ubuntu-latest
    strategy:
      matrix:
        release-type:
          - apk
          # - deb
          # - rpm
    steps:
    - uses: actions/checkout@v6
    - name: Run checks
      run: SECRETS_RELEASE_TYPE="${{ matrix.release-type }}" make release
      env:
        SECRETS_ARTIFACTORY_CREDENTIALS: ${{ secrets.SECRETS_ARTIFACTORY_CREDENTIALS }}

  # github-release:
  #   runs-on: ubuntu-latest
  #   needs: ['release-packages']
  #   steps:
  #   - uses: actions/checkout@v6
  #   - run: make changelog
  #     env:
  #       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  #   - uses: softprops/action-gh-release@v1
  #     with:
  #       # Generated above by `make changelog`:
  #       body_path: CHANGELOG-RELEASE.md
  #     env:
  #       GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/test.yml
================================================
name: test

on:
  push:
    branches:
      - master
    paths-ignore:
      - 'docs/**'
  pull_request:
    paths-ignore:
      - 'docs/**'
  workflow_dispatch:

concurrency: 
  group: ${{ github.head_ref || github.run_id }}-test
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - name: Shellcheck and Hadolint
      run: make lint

  docker-ci:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        docker-env:
          - alma
          - alpine
          #- arch           # disable arch testing for now, see #916
          - debian-gnupg1  # We need to test legacy version of gnupg
          - debian-gnupg2
          - fedora
          - rocky
          - ubuntu
    steps:
    - uses: actions/checkout@v6
    - name: Run checks
      run: SECRETS_DOCKER_ENV="${{ matrix.docker-env }}" make docker-ci

  osx-ci:
    runs-on: macos-latest
    strategy:
      fail-fast: false
      matrix:
        test-verbose: [0, 1]
    steps:
    - uses: actions/checkout@v6
    - name: Install deps
      run: brew install gawk gnupg
    - name: Run checks
      run: SECRETS_TEST_VERBOSE=${{ matrix.test-verbose }} make test

  freebsd-ci:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v6
    - name: Run checks
      id: test
      uses: vmactions/freebsd-vm@v1
      with:
        usesh: true
        prepare: pkg install -y gnupg bash gmake git gawk
        run: gmake test

  windows-wsl-ci:
    runs-on: windows-latest
    steps:
    - uses: Vampire/setup-wsl@v6
      with:
        distribution: Ubuntu-22.04
        update: 'true'
        additional-packages: gnupg make man git gawk file
    - run: git config --global core.autocrlf input
    - uses: actions/checkout@v6
    - shell: wsl-bash {0}
      run: make test


================================================
FILE: .gitignore
================================================
#### joe made this: http://goel.io/joe

#####=== Windows ===#####
# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Windows shortcuts
*.lnk

#####=== Linux ===#####
*~

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

#####=== MacOS ===#####
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear on external disk
.Spotlight-V100
.Trashes

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

#####=== JetBrains ===#####
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties

#####=== SublimeText ===#####
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache

# workspace files are user-specific
*.sublime-workspace

# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project

# sftp configuration file
sftp-config.json

#####=== Jekyll ===#####
_site/
.sass-cache/

#####=== Custom ===#####
# Logic files:
.gitsecret/
git-secret

# Temporary packages:
temp/

# Packaging:
build/
*.deb
*.fpm

# Docs:
docs/man
docs/_posts
docs/_includes/install-*.sh
docs/_includes/version.txt
CHANGELOG-RELEASE.md


================================================
FILE: CHANGELOG.md
================================================
# Changelog

## {{Next Version}}

### Misc

- NOTE: Arch instructions now say to install from source. Arch tests removed temporarily (#916)
- NOTE: there is an issue when repo directory (or a parent dir) contains a space (#135)
- Improve error messaging when we cannot find git repo (#874)
- Temporarily disable apk builds on alpine (#881)
- Have `hide -v` show output from gnupg
- Documentation updates and fixes


## 0.5.0

### Features

- Adds `SECRETS_GPG_ARMOR` env variable to use `gpg --armor`
  when encrypting files, so secret files are stored
  in text format rather than binary (#631)
- Allow gnupg permission warnings in `tell`, `hide`, `reveal`, and `removeperson` (#811)
- `git secret init` now sets `.gitsecret/keys` permission to 0700 (#811)
- Improve verbose and non-verbose output

### Bugfixes

- Fix adding newlines to `.gitignore` entries (#643)
- Fix `cat` and `reveal` on named files while in repo subdir (#710)
- Fix `clean`, `hide`, `reveal` so they only remove marked secret files (#833)
- Fix for `removeperson` if same email is present multiple times (#638)
- Correct error message about files missing from .gitignore

### Misc

- Rename `killperson` command to `removeperson` (#684)
- Improve error messaging decrypting nonexistent files (#706)
- Improve, expand, correct, and update docs (#699)
- Update docs for use with CI/CD server (#675)
- Upgrade bats-core to v1.6.0 (#755)
- Test, and build RPMS, with Rocky and Alma Linux instead of CentOS (#765)
- Automate testing code on windows using WSL (#846)
- Automate testing code on FreeBSD (#455)
- Improve testing of .gitignore contents (#792)
- Automate running verbose tests with SECRETS_TEST_VERBOSE=1 (#794)
- Improve documentation about installing on Windows (#843)


## 0.4.0

### Bugfixes

- Escape filenames with special characters before adding to `.gitignore`
- Better error handling around telling an email twice (#634)
- Fix for `-P` (#647)

### Misc

- Removed `test-kitchen`
- Moved from `travis` to GitHub Actions
- Changed almost all infrastructure code
- Moved away from Bintray to Artifactory
- Changes how GitHub Pages work
- Add security disclaimer for git-secret-killperson
- Improve documentation about releases
- Man page improvements


## Version 0.3.3

### Bugfixes

- In 'tell', warn about disabled, revoked, expired, or invalid keys (#552, #508, #317, #290, #283, #238)
- Error if 'tell' is used on an email address with multiple keys (#552)
- Don't let 'reveal' clobber secret files (#579)
- Updated test key fixture that had expired (#607)

### Misc

- Improve docs about using gpg with git-secret (#577)
- Text improvements and More about security in git-secret.7 man page (#603)
- Reflect changes in ruby bundler during build process
- Upgrade build process to ansible 2.9
- Use shellcheck 0.7.1 with CI, not 'latest' (#609)
- Improve output of `git-secret add`

## Version 0.3.2

### Bugfixes

- Fix mention of version in git-secret add man page (#544)

### Misc

- Update developer docs, especially regarding mac, docker, and test-kitchen (#195)
- Update man pages to mention version documented (#420)

## Version 0.3.1

### Misc

- Update man pages

## Version 0.3.0

### Features

- Support SECRETS_PINENTRY env var for gnupg --pinentry-mode parameter (#221)
- Show output from gnupg if 'hide' fails (#516, #202, #317)
- Add support for Busybox (#478)

### Bugfixes

- Use OSX's mktemp on OSX, even if there's another version in PATH. (#485)
- Make rsync a build requirement on debian (#500)
- Use gnupg1, not gnupg2, when tests specify gnupg1 (#241)
- Note dependencies gawk, bash, and coreutils in linux packages (#493)
- Handle case of key having no email and a comment (#527)
- Avoid blank lines from output of 'clean -v'

### Misc

- Improve messaging and logic around deleting tmp files.
- Add note about secrets and old keys (#499)
- Transition build process from python 2 to python 3 (#487)
- Upgrade build process from ansible 2.5 to ansible 2.8
- Fix build process when installing gnupg2 source deps on Ubuntu
- Close file descriptor 3 when running gnupg subprocesses (#521)
- Small optimization in 'hide'
- Improve code comments
- Update docs to note that git-secret repos modified by git-secret 0.2.3 and
  later are not backward compatible with pre-0.2.3 versions of git-secret. (#536)

## Version 0.2.6

### Features

- git-secret is now available in Fedora, link added to README.md. (#315)
- Support automated testing on windows with Travis CI (#372)
- Support SECRETS_VERBOSE env var to enable verbosity (#323)
- Use gpg without --quiet when decrypting in verbose mode (#394)
- Add -v options to 'tell' and 'reveal', showing gpg output (#320, #395)
- Change 'init' to never ignore .secret files (#362)
- 'add' appends filepaths to .gitignore by default (#225)
- Automate the GitHub release (#411)

### Bugfixes

- Fix 'hide -m' when used as first hide operation (#466)
- Fix code to respect $TMPDIR when generating tmp files (#451)
- Be more careful when deleting test files (#360)
- Use separate directory when testing, instead of using $BATS_TMPDIR directly (#407)
- Fix 'whoknows -l' and related tests on FreeBSD (#454)
- Fix git-secret init when used on busybox (#475)
- Update git-secret.io, fix utils/gh-branch.sh to use 'git all --add' (#344)
- Fix link to homebrew's git-secret in README.md (#310)
- Remove diagnostic output from test results (#324)
- Remove un-needed redirection in 'reveal' (#325)
- Fix link to current contributors in CONTRIBUTING.md (#331)
- Fix tests when running from git hooks (#334)
- Fix typo, remove temp directory in utils/tests.sh (#347)
- Spelling fixes
- Fix re: SECRETS_DIR in 'init' and SECRETS_EXTENSION in test_reveal.bats (#364)
- git-secret will fail if you pass params or filenames that are not understood (#390)
- Use SECRETS_GPG_COMMAND env var in gpg version check (#389)
- Add header to git-secret.7 man page, for debian and doc improvement (#386)
- Respect DESTDIR when installing as per GNU/debian/etc recommendations (#424)
- Use git check-ignore to test for files ignored by git

### Misc

- Improve docs about hide -m option (#467)
- Document SECRETS_VERBOSE and improve env var docs (#396)
- Setting SECRETS_TEST_VERBOSE env var shows debug info during tests (EXPERIMENTAL)
- Add documentation about how to write tests.
- Suppress 'cleaning up temp files' messages unless in a verbose mode.
- Improve git-secret user messaging.
- Update CHANGELOG.md to mention fix for #281 in v0.2.5 (#311)
- Add text explaining git-secret Style Guide and Development Philosophy
- Use Shellcheck on tests/ files, changes for Shellcheck in tests/ (#368)
- Use Shellcheck on MacOS/osx travis tests (#403)
- Show commands run by Makefile as per debian upstream recommendations (#386)
- Upgrade bats-core to v1.1.0, import bats-core into vendor/bats-core (#377)
- Use gawk to parse emails from gpg output
- Optimize code that parses keyrings
- Remove unused code

## Version 0.2.5

### Features

- Add support for FreeBSD (#244)
- Add -l option to whoknows, which shows key expiration dates (#283)
- Add -P option (preserve permissions) to reveal and hide (#172)
- Add -F option (force, changing some errors to warnings) to hide and reveal (#253)
- Allow user to specify name of secret dir at runtime using SECRETS_DIR env var, and test (#247, #250)

### Bugfixes

- Fix issues with spaces in paths and filenames (#226, #135)
- Fix issue when 'hide' used in subdir of repo (#230)
- Fix issues in 'changes' with trailing newlines (#291)
- Fix 'hide' to only count actually hidden files as hidden (#280)
- Fixed bugs and improved error messages (#174)
- Issue error message when unable to hide a secret (#202, #238)
- Accept gpg key with no name, only an email (#227)
- Require keys to be specified by email, as documented (#267)
- Disallow 'git secret tell' or 'killperson' with emails that are not in keyring (also #267)

### Misc

- Added notes about packages and for package maintainers (#281)
- Improve documentation regarding operation with different versions of GPG (#274, #182)
- Documentation improvements, error message and text improvements, and typo fixes (#254)
- git-secret RFC#001 added, documenting a path towards independence from gpg binary formats (#208)
- Add tests for expired gpg keys, and gpg keys with only emails (#276)

## Version 0.2.4

### Features

- Added `git secret cat` feature (#141)

### Bugfixes

- `git secret hide` and `git secret changes` check for files more carefully (#153, #154)

### Misc

- Documentation and error message improvements (#126, #136, #144, #150)
- Build and CI fixes (#152, #179, #186, #188, #189)
- Migrate to `bats-core` bash testing framework

## Version 0.2.3

### Features

- Added `-m` option to `hide` command, files will only be hidden when modifications are detected (#92)
- Changed how path mappings file works: colon delimited FSDB in `.gitsecret/paths/mapping.cfg', so git-secret
  can store checksums of hidden files. Note this means git-secret repos modified by git-secret 0.2.3
  or later are not backward compatible with pre-0.2.3 versions of git-secret. (#92)
- `git secret init` now adds `random_seed` to `.gitignore` (#93)

### Bugfixes

- Dropped `git check-ignore`, using `git add --dry-run` instead to check for ignored files (#105,#38)
- Fixed `gnupg` >= 2.1 CI tests (#6)

### Misc

- Now users can run local CI tests using test-kitchen (#6)
- Migrated travis ci tests to test-kitchen for Linux platforms.
- Added more `gpg` version to test matrix (#99)
- Added CentOS to test matrix (#38,#91)
- All tested Linux platforms now use latest release of `shellcheck`
- Added Alpine to test matrix, and apk is now built. (#75)

## Version 0.2.2

### Features

- Change how the `usage` command works (#48)
- Now `git-secret` works from any place inside `git-tree` (#56)
- Added `-d` option to the `hide` command: it deletes unencrypted files (#62)
- Added new command `changes` to see the diff between the secret files (#64)
- Now it is possible to provide multiple emails to the `killperson` command (#73)
- Now it is possible to provide multiple emails to the `tell` command (#72)

### Bugfixes

- Fixed bug when `_user_required` was not working after re-importing keys (#74)
- Refactored `hide` and `clean` commands to be shorter

### Misc

- Now every doc in this project refer to `git-secret.io` instead of old `gh-pages` website (#71)
- Now installation section is removed from main `man` file (#70)
- Now "See also" sections in the `man` pages are clickable (#69)
- Added "Manual" section to the manuals (#61)
- Added `CentOS` container for `ci` testing (#38)
- Tests are refactored. Added `clean` command tests, removed a lot of hard-coded things, moved tests execution from `./temp` folder to `/tmp`, added a lot of new check in old tests, and some new test cases (#52)
- `shellcheck` is now supported with `make lint`

## Version 0.2.1

### Misc

- Added `CONTRIBUTING.md` and `LICENSE.md`.
- New brand logo in the `README.md`.
- Added autodeploy to `bintray` in `.travis.yml`.
- Now everything is tested inside the `docker`-containers and `OSX` (MacOS) images on `travis`.
- Added `.ci/` folder for continuous integration, refactored `utils/` folder.
- Everything is `shellcheck`ed (except `tests/`).

## Version 0.2.0

### Features

- Added `changes` command to see the difference between current version of the hidden files and the committed one
- Added `-f` option to the `reveal` command to remove prompts

### Bugfixes

- Some bugs are fixed

### Misc

- New installation instructions
- Changed the way files were decrypted, now it is a separate function

## Version 0.1.2

### Features

- Added `-i` option to the `git-secret-add` command, which auto adds unignored files to the `.gitignore`

### Misc

- `.github` templates added
- Documentation improved with `Configuration` section
- `Makefile` improvements with `.PHONY` and `install` target
- Added extra tests: for custom filenames and new features

## Version 0.1.1

### Features

- Added `--dry-run` option to the `git secret` command, which prevents any actions.

### Misc

- Removed animation from docs, now using `asciinema.org`
- `install_full_fixture()` returns a fingerprint
- `uninstall_full_fixture()` receives two args
- Fixed bug when tests were failing with `gpg2`
- New travis strategy: testing both `gpg` and `gpg2`

## Version 0.1.0

### Features

- Implementation of git secret add
- Implementation of git secret clean, with -v option
- Implementation of git secret hide, with -c 'clean' and -v option
- Implementation of git secret init
- Implementation of git secret killperson
- Implementation of git secret list
- Implementation of git secret remove, with -c option
- Implementation of git secret reveal, with -d homedir and -p passphrase options
- Implementation of git secret tell, with -m email and -d homedir options
- Implementation of git secret usage


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Your contributions are always welcome!


## Getting started

1. Create your own or pick an opened issue from the [tracker](https://github.com/sobolevn/git-secret/issues). Take a look at the [`help-wanted` tag](https://github.com/sobolevn/git-secret/labels/help%20wanted)

2. Fork the git-secret repo and then clone the repository using a command like `git clone https://github.com/${YOUR_NAME}/git-secret.git`

3. Make sure that everything works on the current platform by running `make test`.
   You can also try the experimental `SECRETS_TEST_VERBOSE=1 make test`, which will
   show you a lot of debug output while the tests are running.
   Note that 'experimental' features may change or be removed in a future version of `git-secret`.

4. If you want to test on multiple operating systems just push your PR, GitHub Actions will cover everything else

Basically, our `make` file is the only thing you will need to work with this repo.


## Process

### Environment

For development of `git-secret` you should have these tools locally:

- git
- bash
- gawk
- gnupg (or gnupg2), see below if not packaged by your distribution/OS (i.e. MacOS)
- sha256sum (on freebsd and MacOS `shasum` is used instead)
- make

To test `git-secret` you will need:

- [docker](https://www.docker.com/)

### Code style

New features and changes should aim to be as clear, concise, simple, and consistent

1. clear: make it as obvious as possible what the code is doing

2. concise: your PR should be as few characters (not just lines) of changes as _reasonable_.
   However, generally choose clarity over being concise.
   Clarity and conciseness can be in conflict with each other. But
   it's more important for the code to be understandable than for it to be small.
   Therefore favor writing clear code over making shorter diffs in your PRs.

3. simple: this dovetails with the previous two items.
   git-secret is a security product, so it's best to have the code be easy to understand.
   This also aids future development and helps minimize bugs.

4. consistent: Write code that is consistent with the surrounding code and the rest of the git-secret code base.
   Every code base has its own conventions and style that develop and accrete over time.

   Consistency also means that the inputs and outputs of git-secret should be as consistent as reasonable
   with related Unix and git tools, and follow the 'rule of least surprise',
   also known as the 'principle of least astonishment': <https://en.wikipedia.org/wiki/Principle_of_least_astonishment>

We wrote this to clarify our thinking about how git-secret should be written.  Of course, these are philosophical goals,
not necessities for releasing code, so balancing these four ideals _perfectly_ is both unwarranted and impossible.

### Writing PRs

If you're planning a large change to `git-secret` (for example, a lot of lines/characters of diffs, affecting multiple commands,
changing/adding a lot of behavior, or adding multiple command-line options), it's best to discuss the changes in an Issue first.
Also it's often best to implement larger or complex changes as a series of planned-out, smaller PRs,
each making a small set of specific changes. This facilitates discussions of implementation, which often come to light
only after seeing the actual code used to perform a task.

As mentioned above, we seek to be consistent with surrounding git and Unix tools, so when writing changes to git-secret,
think about the input, output, and command-line options that similar Unix commands use.

Our favor toward traditional Unix and git command-style inputs and outputs can also mean it's appropriate to
lean heavily on git and widely-used Unix command features instead of re-implementing them in code.

### Development Process

1. Make changes to the git secret files that need to be changed

2. When making changes to any files inside `src/`, for changes to take effect you will need to rebuild the `git-secret` script with `make clean && make build`

3. Run `shellcheck` against all your changes with `make lint`.
   You should also check your changes for spelling errors using 'aspell -c filename'.

4. Add an entry to CHANGELOG.md, referring to the related issue # if appropriate

5. Change the `man` source file(s) (we write them in markdown) in `man/man1` and `man/man7` to document your changes if appropriate

6. Now, add all your files to the commit with `git add --all` and commit changes with `git commit`.
   Write a good commit message which explains your work

7. When running `git commit` the tests will run automatically, your commit will be canceled if they fail.
   You can run the tests manually with `make clean build test`.

8. Push to your repository, and make a pull-request against `master` branch. It's ideal to have one commit per pull-request,
but don't worry, it's easy to `squash` PRs into a small number of commits when they're merged.

### Branches

We have two long-live branches: `master` for the git-secret code and man pages, and `gh-pages` for the static web site.
The `gh-pages` branch tracks the `master` branch's `docs` folder, and is kept up-to-date using a GitHub Action.

Development looks like this:

> `your-branch` -> `master`

- `master` branch is protected, so only fully tested code goes there. It is also used to create a new `git` tag and a `github` release

By convention, you can name your branches like `issue-###-short-description`, but that's not required.
The `gh-pages` branch is used for the pages at `git-secret.io`. See 'Release Process' below.

### Writing tests

`git-secret` uses [bats-core](https://github.com/bats-core/bats-core) for testing.
See the files in tests/ and the `bats-core` documentation for details.

Because the output of many commands can be affected by the SECRETS_VERBOSE environment
variable (which enables verbosity), it's best not to expect a particular number of lines of
output from commands.

### Release process

To create a new release, (you'll first need permission to commit to the repo, of course):

Update the content of `CHANGELOG.md` for the release (this should be a matter of changing headers),
and update the version string in `src/version.sh`.

When creating a commit inside the `master` branch (it is usually a documentation and changelog update with the version bump inside `src/version.sh`).

Then, push your code to GitHub. It will start the CI.

After all the checks have executed, GitHub Actions will test and build releases for specific platforms.

While CI is doing it's building and testing, finish the release on github by pushing the new tag with:

```bash
git push --tags
```

and then go to https://github.com/sobolevn/git-secret/releases to see that the new release is created. It might take some time.

#### GitHub automated releases

We use GitHub actions to run the release process.
We use `artifactory` as an environment for the release.
You would need to get a review before release would be possible.

It can be reproduced locally with `make release`, but you will need `SECRETS_ARTIFACTORY_CREDENTIALS`.

After packages are released to https://gitsecret.jfrog.io we trigger `release-ci` workflow to test that installation works correctly.

#### Manual releases

Releases to `brew` are made manually, and involve opening a PR on the [Homebrew Core](https://github.com/Homebrew/homebrew-core) repo .
To get started, see the
[Homebrew docs about Formulae-related PRs](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request#formulae-related-pull-request)
and `brew bump-formula-pr --help`

### Downstream Packages

There are several distributions and packaging systems that may already have git-secret packaged for your distribution (although sometimes their versions are not the most current, and we recommend all users upgrade to 0.2.5 or above).

### Notes to Downstream Packagers (Those who make packages for specific OSes/distributions)

First of all, thank you for packaging git-secret for your platform! We appreciate it.

We also would like to welcome you to collaborate or discuss any issues, ideas or thoughts you have about
git-secret by submitting [issue report](https://github.com/sobolevn/git-secret/issues)
(which can also be feature requests) or
[pull requests](https://help.github.com/en/articles/creating-a-pull-request)
via the git repo at
[git-secret on github](https://github.com/sobolevn/git-secret)

Please let us know if there are any changes you'd like to see to the source,
packaging, testing, documentation, or other aspect of git-secret.
We look forward to hearing from you.


## About GnuPG

Here are some links to gnupg documentation that might be useful for those working with git-secret:

- [GnuPG PDF Documentation](https://www.gnupg.org/documentation/manuals/gnupg.pdf)
- [GnuPG doc/DETAILS File](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS)


## Financial contributions

We also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/git-secret).
Anyone can file an expense. If the expense makes sense for the development of the community, it will be "merged" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.


## Credits

### Contributors

Thank you to all the people who have already contributed
to `git-secret` via commits to our git repository!

[![List of contributors](https://opencollective.com/git-secret/contributors.svg?width=890&button=0)](https://github.com/sobolevn/git-secret/contributors)


### Backers

Thank you to all our backers! [[Become a backer](https://opencollective.com/git-secret#backer)]

<object type="image/svg+xml" data="https://opencollective.com/git-secret/tiers/backer.svg?avatarHeight=36&width=600" style="max-width: 100%;"></object>


### Sponsors

Thank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/git-secret#sponsor))

<object type="image/svg+xml" data="https://opencollective.com/git-secret/tiers/sponsor.svg?avatarHeight=36&width=600" style="max-width: 100%;"></object>


================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) 2016 Nikita Sobolev

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: Makefile
================================================
SHELL:=bash
PREFIX?="/usr"
DESTDIR?=

#
# Building:
#

.PHONY: all
all: build

.PHONY: clean
clean:
	@rm -f git-secret

.PHONY: build
build:
	@cat src/version.sh > git-secret
	@cat src/_utils/*.sh src/commands/*.sh >> git-secret
	@cat src/main.sh >> git-secret
	@chmod +x git-secret; sync

.PHONY: install
install:
	"${SHELL}" ./utils/install.sh "${DESTDIR}${PREFIX}"

.PHONY: uninstall
uninstall:
	"${SHELL}" ./utils/uninstall.sh "${DESTDIR}${PREFIX}"

#
# Testing and linting:
#

# The $(shell echo $${PWD}) construct is to access *nix paths under windows
# Under git for windows '$PATH' is set to windows paths, e.g. C:\Something
# Using a sub-shell we get the raw *nix paths, e.g. /c/Something
.PHONY: test
test: clean build
	export SECRETS_PROJECT_ROOT="$(shell echo $${PWD})"; \
	export PATH="$(shell echo $${PWD})/vendor/bats-core/bin:$(shell echo $${PWD}):$(shell echo $${PATH})"; \
	"${SHELL}" ./utils/tests.sh

# We use this script in CI and you can do this too!
# What happens here?
# 1. We pass `SECRETS_DOCKER_ENV` variable into this job
# 2. Based on it, we select a proper `docker` image to run test on
# 3. We execute `make test` inside the `docker` container
.PHONY: docker-ci
docker-ci: clean
	@[ -z "${SECRETS_DOCKER_ENV}" ] \
		&& echo 'SECRETS_DOCKER_ENV is unset' && exit 1 || true
	docker build \
		-f ".ci/docker-ci/$${SECRETS_DOCKER_ENV}/Dockerfile" \
		-t "gitsecret-$${SECRETS_DOCKER_ENV}:latest" .
	docker run --rm \
		--volume="$${PWD}:/code" \
		-w /code \
		"gitsecret-$${SECRETS_DOCKER_ENV}" \
		make test

.PHONY: lint-shell
lint-shell:
	docker pull koalaman/shellcheck:latest
	docker run \
		--volume="$${PWD}:/code" \
		-w /code \
		-e SHELLCHECK_OPTS='-s bash -S style -a' \
		--rm koalaman/shellcheck \
		$$(find src .ci utils tests docs -type f \
			-name '*.sh' -o -name '*.bash' -o -name '*.bats')

.PHONY: lint-docker
lint-docker:
	docker pull hadolint/hadolint:latest-alpine
	docker run \
		--volume="$${PWD}:/code" \
		-w /code \
		--rm hadolint/hadolint \
		hadolint \
			--ignore=DL3008 --ignore=DL3018 --ignore=DL3041 --ignore=DL3028 \
			.ci/*/**/Dockerfile

.PHONY: lint
lint: lint-shell lint-docker

#
# Manuals and docs:
#

.PHONY: clean-man
clean-man:
	@find "man/" -type f ! -name "*.md" -delete

.PHONY: build-man
build-man: build
	docker pull msoap/ruby-ronn
	export GITSECRET_VERSION="$$(./git-secret --version)" && docker run \
		--volume="$${PWD}:/code" \
		-w /code \
		--rm msoap/ruby-ronn \
		ronn --roff \
			--organization=sobolevn \
			--manual="git-secret $${GITSECRET_VERSION}" \
			man/*/*.md

.PHONY: build-docs
build-docs: build-man
	 "${SHELL}" docs/build.sh

.PHONY: docs
docs: build-docs
	docker pull jekyll/jekyll
	docker run \
		--volume="$${PWD}/docs:/code" \
		-w /code \
		-p 4000:4000 \
		--rm jekyll/jekyll \
		jekyll serve --safe --strict_front_matter

.PHONY: changelog
changelog:
	@[ -z "${GITHUB_REPOSITORY}" ] \
		&& echo 'GITHUB_REPOSITORY is unset' && exit 1 || true
	@[ -z "${GITHUB_TOKEN}" ] \
		&& echo 'GITHUB_TOKEN is unset' && exit 1 || true
	docker pull githubchangeloggenerator/github-changelog-generator
	docker run \
		--volume="$${PWD}:/code" \
		-w /code \
		--entrypoint='' \
		-e GITHUB_REPOSITORY \
		-e GITHUB_TOKEN \
		--rm githubchangeloggenerator/github-changelog-generator \
		sh ".ci/github_release_script.sh"

#
# Packaging:
#

.PHONY: build-release
build-release: clean build-man
	@[ -z "${SECRETS_RELEASE_TYPE}" ] \
		&& echo 'SECRETS_RELEASE_TYPE is unset' && exit 1 || true
	docker build \
		-f ".ci/releaser/alpine/Dockerfile" \
		-t "gitsecret-releaser:latest" .
	docker run \
		--volume="$${PWD}:/code" \
		--rm gitsecret-releaser \
		bash "./utils/$${SECRETS_RELEASE_TYPE}/build.sh"

.PHONY: release
release: build-release
	@[ -z "${SECRETS_ARTIFACTORY_CREDENTIALS}" ] \
		&& echo 'SECRETS_ARTIFACTORY_CREDENTIALS is unset' && exit 1 || true
	docker run \
		--volume="$${PWD}:/code" \
		-e SECRETS_ARTIFACTORY_CREDENTIALS \
		-e SECRETS_DEPLOY_DRY_RUN \
		--rm gitsecret-releaser \
		bash "./utils/$${SECRETS_RELEASE_TYPE}/deploy.sh"

.PHONY: release-ci
release-ci:
	@[ -z "${SECRETS_RELEASE_ENV}" ] \
		&& echo 'SECRETS_RELEASE_ENV is unset' && exit 1 || true
	@[ -z "${SECRETS_RELEASE_TYPE}" ] \
		&& echo 'SECRETS_RELEASE_TYPE is unset' && exit 1 || true
	docker build \
		-f ".ci/release-ci/$${SECRETS_RELEASE_ENV}/Dockerfile" \
		-t "gitsecret-release-$${SECRETS_RELEASE_ENV}:latest" .
	docker run --rm \
		--volume="$${PWD}:/code" \
		-w /code \
		"gitsecret-release-$${SECRETS_RELEASE_ENV}" \
		bash -c "set -e; bash "./utils/$${SECRETS_RELEASE_TYPE}/install.sh""


================================================
FILE: README.md
================================================
# git-secret


[![test](https://github.com/sobolevn/git-secret/actions/workflows/test.yml/badge.svg?branch=master&event=push)](https://github.com/sobolevn/git-secret/actions/workflows/test.yml)
[![release-ci](https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml/badge.svg)](https://github.com/sobolevn/git-secret/actions/workflows/release-ci.yml)
[![Homebrew](https://img.shields.io/homebrew/v/git-secret.svg)](https://formulae.brew.sh/formula/git-secret)
[![Supporters](https://img.shields.io/opencollective/all/git-secret.svg?color=gold&label=supporters)](https://opencollective.com/git-secret)

[![git-secret](https://raw.githubusercontent.com/sobolevn/git-secret/gh-pages/images/git-secret-big.png)](https://git-secret.io/)


## What is `git-secret`?

`git-secret` is a bash tool which stores private data inside a git repo.
`git-secret` encrypts files with permitted users' public keys,
allowing users you trust to access encrypted data using pgp and their secret keys.

With `git-secret`, changes to access rights are simplified, and private-public key issues are handled for you.

When someone's permission is revoked, secrets do not need to be changed with `git-secret` -
just remove their key from the repo's keyring using `git secret removeperson their@email.com`,
re-encrypt the files, and they won't be able to decrypt secrets anymore.
If you think the user might have copied the secrets or keys when they had access, then
you should also change the secrets.


## Preview

[![git-secret terminal preview](git-secret.gif)](https://asciinema.org/a/41811?autoplay=1)


## Installation

`git-secret` [supports `brew`](https://formulae.brew.sh/formula/git-secret), just type: `brew install git-secret`

It also supports `apt` and `yum`. You can also use `make` if you want to.
See the [installation section](https://sobolevn.me/git-secret/installation) for the details.

### Requirements

`git-secret` relies on several external packages:

- `bash` since `3.2.57` (it is hard to tell the correct `patch` release)
- `gawk` since `4.0.2`
- `git` since `1.8.3.1`
- `gpg` since `gnupg 1.4` to `gnupg 2.X`
- `sha256sum` since `8.21` (on freebsd and MacOS `shasum` is used instead)


## Contributing

Do you want to help the project? Find an [issue](https://github.com/sobolevn/git-secret/issues)
and send a PR. It is more than welcomed! See [CONTRIBUTING.md](CONTRIBUTING.md) on how to do that.

### Security

In order to encrypt (git-secret hide -m) files only when modified, the path
mappings file tracks sha256sum checksums of the files added (git-secret add) to
git-secret's path mappings filesystem database. Although, the chances of
encountering a sha collision are low, it is recommend that you pad files with
random data for greater security. Or avoid using  the `-m` option altogether.
If your secret file holds more data than just a single password these
precautions should not be necessary, but could be followed for greater
security.

If you found any security related issues, please do not disclose it in public. Send an email to `mail@sobolevn.me`


## Changelog

`git-secret` uses [semver](https://semver.org/). See [CHANGELOG.md](CHANGELOG.md).


## Packagers

Thanks to all the people and groups who package `git-secret` for easier install on particular OSes and distributions!

[![Packaging status](https://repology.org/badge/vertical-allrepos/git-secret.svg)](https://repology.org/project/git-secret/versions)

Here are some packagings of `git-secret` that we're aware of:

- https://formulae.brew.sh/formula/git-secret
- https://packages.ubuntu.com/bionic/git-secret
- https://src.fedoraproject.org/rpms/git-secret
- https://aur.archlinux.org/packages/git-secret/
- https://pkgs.alpinelinux.org/package/edge/testing/x86/git-secret
- https://packages.debian.org/sid/git-secret
- https://github.com/void-linux/void-packages/blob/master/srcpkgs/git-secret/template

Such packages are considered 'downstream' because the git-secret code 'flows' from the `git-secret` [repository](https://git-secret.io/installation)
to the various rpm/deb/dpkg/etc packages that are created for specific OSes and distributions.

We have also added notes specifically for packagers in [CONTRIBUTING.md](CONTRIBUTING.md).


## Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/git-secret#sponsor)]

[![Sponsors](https://opencollective.com/git-secret/tiers/sponsor.svg?width=890)](https://opencollective.com/git-secret)


## Backers

Thanks to all our backers!

[![Backers](https://opencollective.com/git-secret/tiers/backer.svg?width=890&avatarHeight=36)](https://opencollective.com/git-secret)


## Contributors

This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
<a href="https://github.com/sobolevn/git-secret/graphs/contributors"><img src="https://opencollective.com/git-secret/contributors.svg?width=890" /></a>


## License

MIT. See [LICENSE.md](LICENSE.md) for details.


## Thanks

Special thanks to [Elio Qoshi](https://elioqoshi.me/sq/) from [ura](http://ura.design/) for the awesome logo.


================================================
FILE: RFC/RFC001.md
================================================
# RFC 0001 - A stable and forwards compatible public key storage format

**Feature Name:** Stable public key storage

**Status:** Final

**Type:** Enhancement

**Related components:** Core

**Start Date:** 2018-06-14

**Author:** Simon Massey

**GitHub issues:** 

* #136 GnuPG2 2.2 vs 2.1 conflicts in keybox format

## Summary

A new internal public key storage format that avoids forwards compatibility issues between GPG releases. This proposal will keep forwards compatibility with older versions of git-secret. 

## Motivation

GPG maintains backwards compatibility but not forwards compatibility. Running a new GPG version can and will upgrade the keyring storage files in a way that is not recognized by older versions of GPG. This is not normally a problem for typical GPG usage. Users will upgrade and rarely downgrade. It is a problem for git-secret as the keyring storage is committed to git and shared between users. Someone using an older version of GPG can no longer open the upgraded keyring file. 

## Approach

git-secret will move away from using the keyring format as shared storage of public keys. Instead, it will store public keys as exported keys in ASCII armor format. The public key export format is stable and forwards compatible. GPG users will typically be running different GPG or PGP versions and are able to exchange keys successfully. Bugs that affect git-secret's ability to use exported public keys will likely affect typical GPG key exchange usage. Such bugs are likely to be caught and fixed by the wider open source community. 

git-secret may need to store and process meta-data about keys to make it efficient to work with keys that are stored within individual files. It will use the machine-readable ["colon listings format"](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS) for this purpose. 

It is anticipated that `bash` and `gawk` will be sufficient to work efficiently with the new file formats. 

## Design

The new storage format will be implemented as follows: 

1. Keys will be stored in `~/.gitsecret/keys` in `gpg  --armor --export` format. The use of ASCII armor rather than binary format is to make debugging of key related issues easier. The filename of the key will be `<keyid>.pub.gpg` (using Field 5 the "64-bit keyid" of the colon listings format)
1. Key meta data will be stored alongside the key file in the `gpg --keyid-format long --with-colons` format. The file name will be `<keyid>.pub.cln`
1. A folder `~/.gitsecret/cache` will be added to `.gitignore`. At this location, a public keyring will be maintained on a per user bases and won't be shared between users. This is simply a "keyring cache" of the keys used to encrypt files. 

git-secret-tell will: 

1. Scan the set of `*.pub.cln` files to find all currently told identities. If the given identity is in the list do nothing. 
1. If the given identity isn't listed run `gpg  --armor --export` against the users `$HOME` keyring to create the  `<key-id>.pub.gpg`. 
1. Run `--keyid-format long --with-colons` of the exported key to create the `<key-id>.pub.cln`. 

Note that the additional steps to ensure that older versions of git-secret know about the newly told identity will be outlined below. 

git-secret-hide will: 

1. Extract the list of "64-bit keyid"s who are told from the `*.pub.cln` files. Note that multiple identities can be listed against each key. 
1. Checked this against the list of "64-bit keyid"s in the "keyring cache" at `~/.gitsecret/cache`. 
1. Import any missing keys into the "keyring cache". It is anticipated that `gawk` will be sufficient to perform this calculation. 
1. Run the current logic using the "keyring cache". 

Note that the additional steps to ensure that older versions of git-secret know about the newly told user will be outlined below. 

git-secret-whoknows will:

1. The list of identities will be loaded by parsing the `.pub.cln` files. Note that multiple identities can be listed against each key. 

git-secret-usage will:

1. Document the git-secret-migrate command discussed in the next section. 

git-secret-reveal will:

* Be unchanged.  

git-secret-remove will:

* Be unchanged. 

git-secret-list will:

* Be unchanged. 

git-secret-killperson will:

1. Remove the key from the keyring cache.
1. Delete both `<key-id>.pub.gpg` and `<key-id>.pub.cln` files.

git-secret-init will:

1. Add `~/.gitsecret/cache` into `.gitignore`.
1. Run any current logic using the ignored "keyring cache".

git-secret-clean will:

* Be unchanged. 

git-secret-changes will:

1. Show differences the `<key-id>.pub.gpg` and `<key-id>.pub.cln` files in `~/.gitsecret/keys`.

git-secret-add will:

* Be unchanged. 

A new command git-secret-migrate will:

1. Create the folder `~/.gitsecret/cache` and add it to the `.gitignore` file. 
1. Extract all keys from the old keyring generating `<key-id>.pub.gpg` and `<key-id>.pub.cln` files in `~/.gitsecret/keys`

## Version Compatibility

Backwards compatibility will the old keyring storage approach will be maintained as follows:

1. For each changed command a guard will be added that checks for the existence of `.gitsecret/cache`.
1. If the folder exists it proceeds as normal.
1. If it does not exist it will report that the repo was initialized by an older version of git-secret and tell the user to run git-secret-migrate

Forwards compatibility with older versions of git-secret will be maintained as follows. 

git-secret-hide will:

1. Have a guard that will check for the existence of the old keyring. If it exists it will check it for any new public keys and extract them into the new format prior to running. 

git-secret-tell will:

1. Will check for the existence of the old keyring. If it exists it will load the new public key into it. 

git-secret-killperson

1. Will check for the existence of the old keyring. If it exists it will delete the user from it. 


## Drawbacks

To maintain forward compatibility the approach requires the existing logic to kept working for a period of time. We can give a deprecated warning if the forwards compatibility logic is running. The warning can be suppressed using a command-line flag. 

## Alternatives

What other designs have been considered? Unknown. 

What is the impact of not doing this? Team members are locked out of secrets when only one other team member upgrades GPG. This can go undetected until the victims needs the secrets in a hurry for production support. Bad things then happen. 

## Unresolved questions

What parts of the design are still to be done? None. 


================================================
FILE: docs/Gemfile
================================================
source "https://rubygems.org"

group :jekyll_plugins do
  gem "jekyll", ">= 3.6.3"
  gem "jekyll-seo-tag", "~> 2.8.0"
end


================================================
FILE: docs/_config.yml
================================================
# Site settings
title: git-secret
email: mail@sobolevn.me
description: Shell scripts to encrypt your private data inside a git repository.
baseurl: "/git-secret" # the subpath of your site, e.g. /blog
url: "https://sobolevn.me" # the base hostname & protocol for your site

# GitHub links:
github_username: sobolevn
github_changelog: "https://github.com/sobolevn/git-secret/blob/master/CHANGELOG.md"

# Seo settings:
plugins:
  - jekyll-seo-tag

# Build settings
markdown: kramdown


================================================
FILE: docs/_includes/favicons.html
================================================
<link rel="apple-touch-icon" sizes="57x57"
    href="/images/favicons/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60"
    href="/images/favicons/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72"
    href="/images/favicons/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76"
    href="/images/favicons/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114"
    href="/images/favicons/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120"
    href="/images/favicons/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144"
    href="/images/favicons/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152"
    href="/images/favicons/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180"
    href="/images/favicons/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192"
    href="/images/favicons/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32"
    href="/images/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96"
    href="/images/favicons/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16"
    href="/images/favicons/favicon-16x16.png">

<link rel="manifest" href="/images/favicons/manifest.json">

<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage"
    content="/images/favicons/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">


================================================
FILE: docs/_includes/footer.html
================================================
<footer class="site-footer">

  <div class="wrapper">

    <h2 class="footer-heading">{{ site.title }}</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li><a href="http://wemake.services">wemake.services</a></li>
          <li><a href="mailto:{{ site.email }}">{{ site.email }}</a></li>
        </ul>
      </div>

      <div class="footer-col footer-col-2">
        <ul class="social-media-list">
          {% if site.github_username %}
          <li>
            {% include icon-github.html username=site.github_username %}
          </li>
          {% endif %}

          {% if site.twitter_username %}
          <li>
            {% include icon-twitter.html username=site.twitter_username %}
          </li>
          {% endif %}
        </ul>
      </div>

      <div class="footer-col footer-col-3">
        <p>{{ site.description }}</p>
      </div>
    </div>

  </div>

</footer>


================================================
FILE: docs/_includes/head.html
================================================
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</title>
  <meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">

  <link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
  <link rel="canonical"
    href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
  <link rel="alternate" type="application/rss+xml" title="{{ site.title }}"
    href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">

  {% include favicons.html %}

  {% seo %}
</head>


================================================
FILE: docs/_includes/header.html
================================================
<header class="site-header">

  <div class="wrapper">

    <a class="site-title" href="{{ site.baseurl }}/">
      {{ site.title }} v{% include version.txt %}
    </a>

    <div class="site-nav">
      <a href="#" class="menu-icon">
        <svg viewBox="0 0 18 15">
          <path fill="#424242" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z"/>
          <path fill="#424242" d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z"/>
          <path fill="#424242" d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"/>
        </svg>
      </a>

      <div class="trigger">
        <!-- Place this tag where you want the button to render. -->
        <a class="github-button" href="https://github.com/sobolevn/git-secret" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star git-secret on GitHub">
          Star
        </a>
      </div>
    </div>

  </div>

  <nav class="site-navigation">
    <a href="{{ "/installation" | prepend: site.baseurl }}">Installation</a>
    <a href="{{ "/#commands" | prepend: site.baseurl }}">Commands</a>
    <a href="{{ "/plugins" | prepend: site.baseurl }}">External plugins</a>
    <a href="{{ site.github_changelog }}">Changelog</a>
  </nav>

</header>

<!-- Required for GitHub buttons. -->
<script async defer src="https://buttons.github.io/buttons.js"></script>


================================================
FILE: docs/_includes/icon-github.html
================================================
<a href="https://github.com/{{ include.username }}">
    <span class="icon icon--github">{% include icon-github.svg %}</span>
    <span class="username">{{ include.username }}</span>
</a>


================================================
FILE: docs/_includes/icon-twitter.html
================================================
<a href="https://twitter.com/{{ include.username }}">
    <span class="icon icon--twitter">{% include icon-twitter.svg %}</span>
    <span class="username">{{ include.username }}</span>
</a>


================================================
FILE: docs/_includes/why.md
================================================

## Intro

There's a well known issue with deploying and configuring software on servers: 
generally you have to store your private data 
(such as database passwords, application secret-keys, OAuth secret keys, etc) 
outside of the git repository. 

If you do choose to store these secrets unencrypted in your git repo, 
even if the repository is private, it is a security risk to copy 
the secrets everywhere you check out your repo.

What are some drawbacks of storing secrets separately from your git repo?

1. These files are not version controlled. 
Filenames, locations, and passwords change from time to time,
or new information appears, and other information is removed. 
When secrets are stored separately from your repo,
you can not tell for sure which version of the configuration file was used with each commit
or deploy.

2. When building the automated deployment system there will be one extra step: 
download and place these secret-configuration files where they need to be. 
This also means you have to maintain extra secure servers where all your secrets are stored.


### How does `git-secret` solve these problems?

1. `git-secret` encrypts files and stores them inside your `git` repository, providing a history of changes for every commit.
2. `git-secret` doesn't require any extra deploy operations other than providing the appropriate
private key (to allow decryption), and using `git secret reveal`
to decrypt all the secret files.

### What is `git-secret`?

`git-secret` is a bash tool to store your private data inside a `git` repo. 

How's that? Basically, it uses `gpg` to encrypt files with the 
public keys of the users that you trust, and which you have specified with
`git secret tell email@address.id`.
Then these users can decrypt these files using their personal secret key. 

Why deal with all this private/public key stuff? 
To make it easier to manage access rights. 
When you want to remove someone's access, use `git secret removeperson email@address.id`
to delete their public key from your repo's git-secret keyring, and reencrypt the files. 
Then they won't be able to decrypt secrets anymore.

[![git-secret terminal preview](https://raw.githubusercontent.com/sobolevn/git-secret/master/git-secret.gif)](https://asciinema.org/a/41811?autoplay=1)


================================================
FILE: docs/_layouts/default.html
================================================
<!DOCTYPE html>
<html>

  {% include head.html %}

  <body>

    {% include header.html %}

    <div class="page-content">
      <div class="wrapper">
        {{ content }}
      </div>
    </div>

    {% include footer.html %}

    <!-- Place this tag in your head or just before your close body tag. -->
    <script async defer src="https://buttons.github.io/buttons.js"></script>
  </body>

</html>


================================================
FILE: docs/_layouts/page.html
================================================
---
layout: default
---
<article class="post">

  <header class="post-header">
    <h1 class="post-title">{{ page.title }}</h1>
  </header>

  <div class="post-content">
    {{ content }}
  </div>

</article>


================================================
FILE: docs/_layouts/post.html
================================================
---
layout: default
---
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">

  <header class="post-header">
    <h1 class="post-title" itemprop="name headline">
        {{ page.title }}
    </h1>

    <p class="post-meta">
        <time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">
            {{ page.date | date: "%b %-d, %Y" }}
        </time>

        {% if page.author %}
            • <span itemprop="author" itemscope itemtype="http://schema.org/Person">
                <span itemprop="name">
                    {{ page.author }}
                </span>
            </span>
        {% endif %}
    </p>
  </header>

  <div class="post-content" itemprop="articleBody">
    {{ content }}
  </div>

</article>


================================================
FILE: docs/_sass/_base.scss
================================================
/**
 * Reset some basic elements
 */
body, h1, h2, h3, h4, h5, h6,
p, blockquote, pre, hr,
dl, dd, ol, ul, figure {
    margin: 0;
    padding: 0;
}



/**
 * Basic styling
 */
body {
    font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
    color: $text-color;
    background-color: $background-color;
    -webkit-text-size-adjust: 100%;
    -webkit-font-feature-settings: "kern" 1;
    -moz-font-feature-settings: "kern" 1;
    -o-font-feature-settings: "kern" 1;
    font-feature-settings: "kern" 1;
    font-kerning: normal;
}



/**
 * Set `margin-bottom` to maintain vertical rhythm
 */
h1, h2, h3, h4, h5, h6,
p, blockquote, pre,
ul, ol, dl, figure,
%vertical-rhythm {
    margin-bottom: $spacing-unit / 2;
}



/**
 * Images
 */
img {
    max-width: 100%;
    vertical-align: middle;
}



/**
 * Figures
 */
figure > img {
    display: block;
}

figcaption {
    font-size: $small-font-size;
}



/**
 * Lists
 */
ul, ol {
    margin-left: $spacing-unit;
}

li {
    > ul,
    > ol {
         margin-bottom: 0;
    }
}



/**
 * Headings
 */
h1, h2, h3, h4, h5, h6 {
    font-weight: $base-font-weight;
}



/**
 * Links
 */
a {
    color: $brand-color;
    text-decoration: none;

    &:visited {
        color: darken($brand-color, 15%);
    }

    &:hover {
        color: $text-color;
        text-decoration: underline;
    }
}



/**
 * Blockquotes
 */
blockquote {
    color: $purple-color;
    border-left: 4px solid $purple-color-light;
    padding-left: $spacing-unit / 2;
    font-size: 18px;
    letter-spacing: -1px;
    font-style: italic;

    > :last-child {
        margin-bottom: 0;
    }
}



/**
 * Code formatting
 */
pre,
code {
    font-size: 15px;
    border: 1px solid $purple-color-light;
    border-radius: 3px;
    background-color: #eef;
}

code {
    padding: 1px 5px;
}

pre {
    padding: 8px 12px;
    overflow-x: auto;

    > code {
        border: 0;
        padding-right: 0;
        padding-left: 0;
    }
}



/**
 * Wrapper
 */
.wrapper {
    max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
    max-width:         calc(#{$content-width} - (#{$spacing-unit} * 2));
    margin-right: auto;
    margin-left: auto;
    padding-right: $spacing-unit;
    padding-left: $spacing-unit;
    @extend %clearfix;

    @include media-query($on-laptop) {
        max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
        max-width:         calc(#{$content-width} - (#{$spacing-unit}));
        padding-right: $spacing-unit / 2;
        padding-left: $spacing-unit / 2;
    }
}



/**
 * Clearfix
 */
%clearfix {

    &:after {
        content: "";
        display: table;
        clear: both;
    }
}



/**
 * Icons
 */
.icon {

    > svg {
        display: inline-block;
        width: 16px;
        height: 16px;
        vertical-align: middle;

        path {
            fill: $purple-color;
        }
    }
}


================================================
FILE: docs/_sass/_layout.scss
================================================
/**
 * Site header
 */
.site-header {
    border-top: 5px solid $purple-color-dark;
    border-bottom: 1px solid $purple-color-light;
    min-height: 56px;

    // Positioning context for the mobile navigation icon
    position: relative;
}

.site-title {
    font-size: 26px;
    font-weight: 300;
    line-height: 56px;
    letter-spacing: -1px;
    margin-bottom: 0;
    float: left;

    &,
    &:visited {
        color: $purple-color-dark;
    }
}

.site-nav {
    @extend %clearfix;
    float: right;
    line-height: 56px;

    .menu-icon {
        display: none;
    }

    .page-link {
        color: $text-color;
        line-height: $base-line-height;

        // Gaps between nav items, but not on the last one
        &:not(:last-child) {
            margin-right: 20px;
        }
    }

    @include media-query($on-palm) {
        position: absolute;
        top: 9px;
        right: $spacing-unit / 2;
        background-color: $background-color;
        border: 1px solid $purple-color-light;
        border-radius: 5px;
        text-align: right;

        .menu-icon {
            display: block;
            float: right;
            width: 36px;
            height: 26px;
            line-height: 0;
            padding-top: 10px;
            text-align: center;

            > svg {
                width: 18px;
                height: 15px;

                path {
                    fill: $purple-color-dark;
                }
            }
        }

        .trigger {
            clear: both;
            display: none;
        }

        &:hover .trigger, &:active .trigger {
            display: block;
            padding-bottom: 5px;
        }

        .page-link {
            display: block;
            padding: 5px 10px;

            &:not(:last-child) {
                margin-right: 0;
            }
            margin-left: 20px;
        }
    }

    .trigger {
        padding-top: 13px;
    }
}



/**
 * Site footer
 */
.site-footer {
    border-top: 1px solid $purple-color-light;
    padding: $spacing-unit 0;
}

.footer-heading {
    font-size: 18px;
    margin-bottom: $spacing-unit / 2;
}

.contact-list,
.social-media-list {
    list-style: none;
    margin-left: 0;
}

.footer-col-wrapper {
    font-size: 15px;
    color: $grey-color;
    margin-left: -$spacing-unit / 2;
    @extend %clearfix;
}

.footer-col {
    float: left;
    margin-bottom: $spacing-unit / 2;
    padding-left: $spacing-unit / 2;
}

.footer-col-1 {
    width: -webkit-calc(35% - (#{$spacing-unit} / 2));
    width:         calc(35% - (#{$spacing-unit} / 2));
}

.footer-col-2 {
    width: -webkit-calc(20% - (#{$spacing-unit} / 2));
    width:         calc(20% - (#{$spacing-unit} / 2));
}

.footer-col-3 {
    width: -webkit-calc(45% - (#{$spacing-unit} / 2));
    width:         calc(45% - (#{$spacing-unit} / 2));
}

@include media-query($on-laptop) {
    .footer-col-1,
    .footer-col-2 {
        width: -webkit-calc(50% - (#{$spacing-unit} / 2));
        width:         calc(50% - (#{$spacing-unit} / 2));
    }

    .footer-col-3 {
        width: -webkit-calc(100% - (#{$spacing-unit} / 2));
        width:         calc(100% - (#{$spacing-unit} / 2));
    }
}

@include media-query($on-palm) {
    .footer-col {
        float: none;
        width: -webkit-calc(100% - (#{$spacing-unit} / 2));
        width:         calc(100% - (#{$spacing-unit} / 2));
    }
}



/**
 * Page content
 */
.page-content {
    padding: $spacing-unit 0;
}

.page-heading {
    font-size: 20px;
}

.post-list {
    li {
        margin-bottom: 10px;
    }
}

.post-meta {
    font-size: $small-font-size;
    color: $grey-color;
}

.post-link {
    display: block;
    font-size: 24px;
}



/**
 * Posts
 */
.post-header {
    margin-bottom: $spacing-unit;
}

.post-title {
    font-size: 42px;
    letter-spacing: -1px;
    line-height: 1;

    @include media-query($on-laptop) {
        font-size: 36px;
    }
}

.post-content {
    margin-bottom: $spacing-unit;

    h2 {
        font-size: 32px;

        @include media-query($on-laptop) {
            font-size: 28px;
        }
    }

    h3 {
        font-size: 26px;

        @include media-query($on-laptop) {
            font-size: 22px;
        }
    }

    h4 {
        font-size: 20px;

        @include media-query($on-laptop) {
            font-size: 18px;
        }
    }
}


/**
 * Navigation
 */
.site-navigation {
    @extend .wrapper;

    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;

    a {
        color: $purple-color-dark;

        @include media-query($on-laptop) {
            flex-basis: 100%;
            text-align: center;
        }
    }
}


/**
 * Homepage
 */
 .home {
    .home-logo-image {
        margin-top: 50px;
        margin-bottom: 70px;
    }
 }


================================================
FILE: docs/_sass/_syntax-highlighting.scss
================================================
/**
 * Syntax highlighting styles
 */
.highlight {
    background: #fff;
    @extend %vertical-rhythm;

    .highlighter-rouge & {
      background: #eef;
    }

    .c     { color: #998; font-style: italic } // Comment
    .err   { color: #a61717; background-color: #e3d2d2 } // Error
    .k     { font-weight: bold } // Keyword
    .o     { font-weight: bold } // Operator
    .cm    { color: #998; font-style: italic } // Comment.Multiline
    .cp    { color: #999; font-weight: bold } // Comment.Preproc
    .c1    { color: #998; font-style: italic } // Comment.Single
    .cs    { color: #999; font-weight: bold; font-style: italic } // Comment.Special
    .gd    { color: #000; background-color: #fdd } // Generic.Deleted
    .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
    .ge    { font-style: italic } // Generic.Emph
    .gr    { color: #a00 } // Generic.Error
    .gh    { color: #999 } // Generic.Heading
    .gi    { color: #000; background-color: #dfd } // Generic.Inserted
    .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
    .go    { color: #888 } // Generic.Output
    .gp    { color: #555 } // Generic.Prompt
    .gs    { font-weight: bold } // Generic.Strong
    .gu    { color: #aaa } // Generic.Subheading
    .gt    { color: #a00 } // Generic.Traceback
    .kc    { font-weight: bold } // Keyword.Constant
    .kd    { font-weight: bold } // Keyword.Declaration
    .kp    { font-weight: bold } // Keyword.Pseudo
    .kr    { font-weight: bold } // Keyword.Reserved
    .kt    { color: #458; font-weight: bold } // Keyword.Type
    .m     { color: #099 } // Literal.Number
    .s     { color: #d14 } // Literal.String
    .na    { color: #008080 } // Name.Attribute
    .nb    { color: #0086B3 } // Name.Builtin
    .nc    { color: #458; font-weight: bold } // Name.Class
    .no    { color: #008080 } // Name.Constant
    .ni    { color: #800080 } // Name.Entity
    .ne    { color: #900; font-weight: bold } // Name.Exception
    .nf    { color: #900; font-weight: bold } // Name.Function
    .nn    { color: #555 } // Name.Namespace
    .nt    { color: #000080 } // Name.Tag
    .nv    { color: #008080 } // Name.Variable
    .ow    { font-weight: bold } // Operator.Word
    .w     { color: #bbb } // Text.Whitespace
    .mf    { color: #099 } // Literal.Number.Float
    .mh    { color: #099 } // Literal.Number.Hex
    .mi    { color: #099 } // Literal.Number.Integer
    .mo    { color: #099 } // Literal.Number.Oct
    .sb    { color: #d14 } // Literal.String.Backtick
    .sc    { color: #d14 } // Literal.String.Char
    .sd    { color: #d14 } // Literal.String.Doc
    .s2    { color: #d14 } // Literal.String.Double
    .se    { color: #d14 } // Literal.String.Escape
    .sh    { color: #d14 } // Literal.String.Heredoc
    .si    { color: #d14 } // Literal.String.Interpol
    .sx    { color: #d14 } // Literal.String.Other
    .sr    { color: #009926 } // Literal.String.Regex
    .s1    { color: #d14 } // Literal.String.Single
    .ss    { color: #990073 } // Literal.String.Symbol
    .bp    { color: #999 } // Name.Builtin.Pseudo
    .vc    { color: #008080 } // Name.Variable.Class
    .vg    { color: #008080 } // Name.Variable.Global
    .vi    { color: #008080 } // Name.Variable.Instance
    .il    { color: #099 } // Literal.Number.Integer.Long
}


================================================
FILE: docs/build.sh
================================================
#!/usr/bin/env bash

# Should be called from the root folder, not inside `docs/` folder
# See `make build-docs`

set -e

MAN_LOCATION='man/man1'
MAN7_LOCATION='man/man7'
POSTS_LOCATION='docs/_posts'


function checkout_manuals {
  cp -R man/ docs/man
}


function copy_to_posts {
  # Cleaning old files:
  rm -f "$POSTS_LOCATION/*.md"
  rm -rf "$POSTS_LOCATION"
  mkdir -p "$POSTS_LOCATION"

  # Moving new command files:
  local timestamp
  local current_date

  timestamp=$(date "+%Y-%m-%d %H:%M:%S %z")
  current_date=$(date "+%Y-%m-%d")

  # Creating command reference:
  for com in "$MAN_LOCATION"/git-secret-*.1.md; do
    local short_name
    short_name=$(echo "$com" | sed -n "s|$MAN_LOCATION/\(.*\)\.1\.md|\1|p")
    local command_header="---
layout: post
title: '${short_name}'
date: ${timestamp}
permalink: ${short_name}
categories: command
---"

    local post_filename="$POSTS_LOCATION/${current_date}-${short_name}.md"
    echo "$command_header" > "$post_filename"
    cat "$com" >> "$post_filename"
  done

  # Creating main usage file:
  local usage_header="---
layout: post
title: 'git-secret'
date: ${timestamp}
permalink: git-secret
categories: usage
---"
  local usage_filename="$POSTS_LOCATION/${current_date}-git-secret.md"
  echo "$usage_header" > "$usage_filename"
  cat "$MAN7_LOCATION/git-secret.7.md" >> "$usage_filename"
}


function copy_install_scripts {
  # We test these scripts using `release-ci`,
  # so, installation instructions will always be up-to-date:
  cp utils/deb/install.sh docs/_includes/install-deb.sh
  cp utils/rpm/install.sh docs/_includes/install-rpm.sh
  cp utils/apk/install.sh docs/_includes/install-apk.sh
}


function copy_version {
   ./git-secret --version > docs/_includes/version.txt
}


checkout_manuals
copy_to_posts
copy_install_scripts
copy_version


================================================
FILE: docs/css/main.scss
================================================
---
# Only the main Sass file needs front matter (the dashes are enough)
---
@charset "utf-8";



// Our variables
$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
$base-font-size:   16px;
$base-font-weight: 400;
$small-font-size:  $base-font-size * 0.875;
$base-line-height: 1.5;

$spacing-unit:     30px;

$text-color:       #111;
$background-color: #fdfdfd;

$grey-color:       #828282;
$grey-color-light: lighten($grey-color, 40%);
$grey-color-dark:  darken($grey-color, 25%);

$purple-color:       rgb(238, 81, 59);
$purple-color-light: lighten($purple-color, 40%);
$purple-color-dark:  darken($purple-color, 25%);

$brand-color:      $purple-color;

// Width of the content area
$content-width:    800px;

$on-palm:          600px;
$on-laptop:        800px;



// Use media queries like this:
// @include media-query($on-palm) {
//     .wrapper {
//         padding-right: $spacing-unit / 2;
//         padding-left: $spacing-unit / 2;
//     }
// }
@mixin media-query($device) {
    @media screen and (max-width: $device) {
        @content;
    }
}



// Import partials from `sass_dir` (defaults to `_sass`)
@import
        "base",
        "layout",
        "syntax-highlighting"
;


================================================
FILE: docs/feed.xml
================================================
---
layout: null
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ site.title | xml_escape }}</title>
    <description>{{ site.description | xml_escape }}</description>
    <link>{{ site.url }}{{ site.baseurl }}/</link>
    <atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml"/>
    <pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
    <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
    <generator>Jekyll v{{ jekyll.version }}</generator>
    {% for post in site.posts limit:10 %}
      <item>
        <title>{{ post.title | xml_escape }}</title>
        <description>{{ post.content | xml_escape }}</description>
        <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
        <link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link>
        <guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid>
        {% for tag in post.tags %}
        <category>{{ tag | xml_escape }}</category>
        {% endfor %}
        {% for cat in post.categories %}
        <category>{{ cat | xml_escape }}</category>
        {% endfor %}
      </item>
    {% endfor %}
  </channel>
</rss>


================================================
FILE: docs/images/favicons/browserconfig.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

================================================
FILE: docs/images/favicons/manifest.json
================================================
{
 "name": "App",
 "icons": [
  {
   "src": "\/android-icon-36x36.png",
   "sizes": "36x36",
   "type": "image\/png",
   "density": "0.75"
  },
  {
   "src": "\/android-icon-48x48.png",
   "sizes": "48x48",
   "type": "image\/png",
   "density": "1.0"
  },
  {
   "src": "\/android-icon-72x72.png",
   "sizes": "72x72",
   "type": "image\/png",
   "density": "1.5"
  },
  {
   "src": "\/android-icon-96x96.png",
   "sizes": "96x96",
   "type": "image\/png",
   "density": "2.0"
  },
  {
   "src": "\/android-icon-144x144.png",
   "sizes": "144x144",
   "type": "image\/png",
   "density": "3.0"
  },
  {
   "src": "\/android-icon-192x192.png",
   "sizes": "192x192",
   "type": "image\/png",
   "density": "4.0"
  }
 ]
}

================================================
FILE: docs/index.html
================================================
---
layout: default
---

<div class="home">

  <img src="{{ "/images/git-secret-big.png" | prepend: site.baseurl }}"
       alt="git-secret"
       title="git-secret"
       class="home-logo-image" />

  <h1>Synopsis</h1>

  {% capture markdown_file %}
    {% include why.md %}
  {% endcapture %}

  {{ markdown_file | markdownify }}

  {% for post in site.categories.usage %}
    {{ post.content }}
  {% endfor %}

  <h2 class="page-heading" id="commands">Command Reference</h2>

  <ul class="post-list">
    {% for post in site.categories.command %}
      <li>
        <h2>
          <a class="post-link" href="{{ post.url | prepend: site.baseurl }}">
            {{ post.title }}
          </a>
        </h2>
      </li>
    {% endfor %}
  </ul>

  <p class="rss-subscribe">
    subscribe
    <a href="{{ "/feed.xml" | prepend: site.baseurl }}">via RSS</a>
  </p>

</div>


================================================
FILE: docs/installation.md
================================================
---
layout: default
---

# Installation

## Dependencies

`git-secret` relies on two dependencies: `git` and `gpg`. Download and install them before using this project. `git-secret` is tested to work with:

```
git version 2.7.0
gpg (GnuPG) 1.4.20
```

## Supported platforms

`git-secret` is tested with `Mac OS X` >= 10.9, `Ubuntu` >= 14.04, `Debian` >= 8.3, 
`Fedora` / `Rocky Linux` / `AlmaLinux`, `FreeBSD`, and `Windows` >= 10 using `WSL`.
You can check the full list of automated test platforms
[here](https://github.com/sobolevn/git-secret/blob/master/.github/workflows/test.yml).

We are always interested in getting `git-secret` working and tested on additional systems.
If you get `git-secret` working on a new system and the tests pass for you, 
you can add a GitHub Action to test your platform to that file. 
Also we welcome improvements to tests or `git-secret` code for any platform.

## Installation process

There are several ways to install `git-secret`, depending on your OS and distribution.
They generally all have different installation processes, so we only go into 
a short explanation of each. 
(We welcome documentation improvements.)

---

### Mac OS X / Homebrew

This is a packaging system for OSX. To install `git-secret` on OSX, you can install
`homebrew` and then use:

```bash
brew install git-secret
````

---

### Debian-Type Systems / `deb` package

`deb` is a packaging system for [Debian](https://www.debian.org/) and related linux
distributions.

You can find the `deb` repository [here](https://gitsecret.jfrog.io/artifactory/git-secret-deb/).
Pre-requirements: make sure you have installed `apt-transport-https` and `ca-certificates`

```bash
{% include install-deb.sh %}
```

---

### Red Hat Systems / `rpm` package

`rpm` is a packaging system for Fedora, CentOS, and other Red Hat based linux distributions.
You can find the `rpm` repository [here](https://gitsecret.jfrog.io/artifactory/git-secret-rpm/).

```bash
{% include install-rpm.sh %}
```

---

### Alpine Systems / `apk` package

`apk` is a packaging system for Alpine.
You can find the `apk` `git-secret` packaging 
[here](https://gitsecret.jfrog.io/artifactory/git-secret-apk/),
and you can see a list of supported architectures 
[here](https://github.com/sobolevn/git-secret/blob/master/utils/apk/meta.sh)

```bash
{% include install-apk.sh %}
```

---

### Arch Linux

Use `Manual Installation` method described below.

---

### Windows / `WSL`, `Cygwin`, `MSYS`, or `Mingw-w64`

`git-secret` depends on many unix tools and features that Windows systems do not usually
include by default.  Therefore to get `git-secret` running on Windows you have to 
install these tools, probably using one of the toolkits described below. 
Each has a different install and setup process. There may also be other 
ways to install the unix prerequisites on Windows.

Once the prerequisite unix tools are installed,
you can use the Manual Installation instructions below to 
manually install `git-secret` (see below).  

Some ways to install the required unix tools on windows include
WSL, CYGWIN, MSYS, and Mingw-w64 
(internally, these tools may share some components).

Documenting how each is installed and used is beyond the scope of this document, 
so we will cover the topic in broad strokes. Improvements to this documentation
(or any other git-secret documentation) are welcome. 

Again, after you install the unix tools needed, you can install 
`git-secret` on windows using the `Manual Installation` steps below.

#### WSL

Perhaps the easiest way to get `git-secret` operating on windows is using `WSL`
(if your system supports it). 
Here are instructions to install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install)
You'll need to install these additional packages: `gnupg`, `make`, `man`, `git`, `gawk`, `file`.

We have successfully set up automated testing of `git-secret` on `WSL`, 
so we are confident this method works.

#### Mingw-w64

Another way to install the prerequisites for `git-secret` on Windows is to use 
[Mingw-w64](https://www.mingw-w64.org/) and install the needed packages.
By default, the `Mingw-w64` installation will be saved to `C:\msys64`. You'll need to 
install `make` and probably other tools such as `gnupg`, `make`, `man`, `git`, and `gawk`. 
(This list might not be complete). 

#### MSYS and Cygwin

`git-secret` also works with [MSYS](https://www.msys2.org/)
and [Cygwin](https://www.cygwin.com/), and we have gotten _most_ of the way to getting
`git-secret`'s self-tests running on these setups with Windows (see 
[windows-related issues](https://github.com/sobolevn/git-secret/issues?q=is%3Aissue+is%3Aopen+windows)).

We welcome contributions to `git-secret` and its documentation .

---

### Manual Installation

```bash
git clone https://github.com/sobolevn/git-secret.git git-secret
cd git-secret && make build
PREFIX="/usr/local" make install
```

Note that you can change `PREFIX` to be any directory you subsequently include in in your `PATH`
environment variable. We generally recommend you stick to the default 
install locations for simplicity, but if you know what you're doing you are welcome to change it.



================================================
FILE: docs/plugins.md
================================================
---
layout: default
---

# External plugins

Here's a list of external plugins for `git-secret` developed by other awesome developers:

- [git-secret-diff](https://github.com/msilvestre/git-secret-diff) adds `git secret diff` command similar to `git diff` to see changes in your secrets in different commits


================================================
FILE: man/man1/git-secret-add.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-ADD" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-add\fR \- starts to track added files\.
.
.SH "SYNOPSIS"
.
.nf

git secret add [\-v] [\-i] <pathspec>\.\.\.
.
.fi
.
.SH "DESCRIPTION"
\fBgit secret add\fR \- tells \fBgit secret\fR which files hold secrets\.
.
.P
Adds filepath(s) into \fB\.gitsecret/paths/mapping\.cfg\fR\. (It is not recommended to alter \fB\.gitsecret/paths/mapping\.cfg\fR manually\.)
.
.P
As of 0\.2\.6, this command also ensures the filepath is in \fB\.gitignore\fR as the contents are now considered secret and should not be committed into the repository unencrypted\.
.
.P
The \fBadd\fR action will fail unless there are already users in \fBgit\-secret\fR\'s keyring\.
.
.P
(See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information about renaming the \.gitsecret folder using the SECRETS_DIR environment variable\.
.
.SH "OPTIONS"
.
.nf

\-v  \- verbose, shows extra information\.
\-i  \- does nothing, adding paths to \.gitignore is now the default behavior\.
\-h  \- shows this help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-add\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-init(1) \fIhttps://git\-secret\.io/git\-secret\-init\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR


================================================
FILE: man/man1/git-secret-add.1.md
================================================
git-secret-add - starts to track added files.
=============================================

## SYNOPSIS

    git secret add [-v] [-i] <pathspec>...


## DESCRIPTION
`git secret add` - tells `git secret` which files hold secrets.

Adds filepath(s) into `.gitsecret/paths/mapping.cfg`.
(It is not recommended to alter `.gitsecret/paths/mapping.cfg` manually.)

As of 0.2.6, this command also ensures the filepath is in `.gitignore`
as the contents are now considered secret and should not be committed into the repository unencrypted.

The `add` action will fail unless there are already users in `git-secret`'s keyring.


(See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret
folder using the SECRETS_DIR environment variable.

## OPTIONS

    -v  - verbose, shows extra information.
    -i  - does nothing, adding paths to .gitignore is now the default behavior.
    -h  - shows this help.


## MANUAL

Run `man git-secret-add` to see this document.


## SEE ALSO

[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),
[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal)


================================================
FILE: man/man1/git-secret-cat.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-CAT" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-cat\fR \- decrypts files passed on command line to stdout\.
.
.SH "SYNOPSIS"
.
.nf

git secret cat [\-d dir] [\-p password] filename [filenames]
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-cat\fR \- prints the decrypted contents of the passed files\.
.
.P
As with \fBgit\-secret\-reveal\fR, you\'ll need to have the private key for one of the emails allowed to decrypt this repo in your personal keyring\.
.
.P
Note this command can be affected by the \fBSECRETS_PINENTRY\fR environment variable\. See (See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information using \fBSECRETS_PINENTRY\fR\.
.
.SH "OPTIONS"
.
.nf

\-d  \- specifies `\-\-homedir` option for the `gpg`, use this option if you store your keys in a custom location\.
\-p  \- specifies password for noinput mode, adds `\-\-passphrase` option for `gpg`\.
\-h  \- shows help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-cat\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-init(1) \fIhttps://git\-secret\.io/git\-secret\-init\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR


================================================
FILE: man/man1/git-secret-cat.1.md
================================================
git-secret-cat - decrypts files passed on command line to stdout.
=============================================

## SYNOPSIS

    git secret cat [-d dir] [-p password] filename [filenames]


## DESCRIPTION
`git-secret-cat` - prints the decrypted contents of the passed files.

As with `git-secret-reveal`, you'll need to have the private key for one of the emails allowed to
decrypt this repo in your personal keyring.

Note this command can be affected by the `SECRETS_PINENTRY` environment variable. See
(See [git-secret(7)](https://git-secret.io/git-secret) for information using `SECRETS_PINENTRY`.


## OPTIONS

    -d  - specifies `--homedir` option for the `gpg`, use this option if you store your keys in a custom location.
    -p  - specifies password for noinput mode, adds `--passphrase` option for `gpg`.
    -h  - shows help.


## MANUAL

Run `man git-secret-cat` to see this document.


## SEE ALSO

[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-cat)


================================================
FILE: man/man1/git-secret-changes.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-CHANGES" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-changes\fR \- view diff of the hidden files\.
.
.SH "SYNOPSIS"
.
.nf

git secret changes [\-h] [\-d dir] [\-p password] [pathspec]\.\.\.
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-changes\fR \- shows changes between the current versions of secret files and encrypted versions\.
.
.P
If no filenames are provided, changes to all hidden files will be shown\. Alternately, provide any number of hidden files to this command as arguments, and it will show changes for those files\.
.
.P
Note files must be specified by their unencrypted names, without the \fB\.secret\fR suffix, (or whatever is specified by the \fBSECRETS_EXTENSION\fR environment variable)\.
.
.P
Note also this command can be affected by the \fBSECRETS_PINENTRY\fR environment variable\. See (See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information using \fBSECRETS_PINENTRY\fR\.
.
.SH "OPTIONS"
.
.nf

\-d  \- specifies `\-\-homedir` option for the `gpg`\. Use this option if you store your keys in a custom location\.
\-p  \- specifies password for noinput mode, adds `\-\-passphrase` option for `gpg`\.
\-h  \- shows help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-changes\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR


================================================
FILE: man/man1/git-secret-changes.1.md
================================================
git-secret-changes - view diff of the hidden files.
===================================================

## SYNOPSIS

    git secret changes [-h] [-d dir] [-p password] [pathspec]...


## DESCRIPTION
`git-secret-changes` - shows changes between the current versions of secret files and encrypted versions.

If no filenames are provided, changes to all hidden files will be shown. Alternately,
provide any number of hidden files to this command as arguments, and it will show changes for those files.

Note files must be specified by their unencrypted names, without the `.secret` suffix,
(or whatever is specified by the `SECRETS_EXTENSION` environment variable).

Note also this command can be affected by the `SECRETS_PINENTRY` environment variable. See
(See [git-secret(7)](https://git-secret.io/git-secret) for information using `SECRETS_PINENTRY`.


## OPTIONS

    -d  - specifies `--homedir` option for the `gpg`. Use this option if you store your keys in a custom location.
    -p  - specifies password for noinput mode, adds `--passphrase` option for `gpg`.
    -h  - shows help.


## MANUAL

Run `man git-secret-changes` to see this document.


## SEE ALSO

[git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),
[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),
[git-secret-cat(1)](https://git-secret.io/git-secret-cat)


================================================
FILE: man/man1/git-secret-clean.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-CLEAN" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-clean\fR \- removes all the hidden files\.
.
.SH "SYNOPSIS"
.
.nf

git secret clean [\-v]
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-clean\fR \- deletes all files in the current \fBgit\-secret\fR repo that end with \fB\.secret\fR\.
.
.P
You can change the extension \fBgit\-secret\fR uses for encrypted files with the \fBSECRETS_EXTENSION\fR environment variable\.
.
.P
Note that it will delete any files ending in \fB\.secret\fR, even if they are not tracked by \fBgit\-secret\fR\.
.
.P
Also note that this command does not delete unencrypted versions of files\.
.
.P
Verbose mode, enabled with the \fB\-v\fR option, displays the filenames deleted\.
.
.SH "OPTIONS"
.
.nf

\-v  \- verbose mode, shows which files are deleted\.
\-h  \- shows this help\.
.
.fi
.
.P
You can also enable verbosity using the SECRETS_VERBOSE environment variable, as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.SH "MANUAL"
Run \fBman git\-secret\-clean\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-whoknows(1) \fIhttps://git\-secret\.io/git\-secret\-whoknows\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-remove(1) \fIhttps://git\-secret\.io/git\-secret\-remove\fR, git\-secret\-removeperson(1) \fIhttps://git\-secret\.io/git\-secret\-removeperson\fR


================================================
FILE: man/man1/git-secret-clean.1.md
================================================
git-secret-clean - removes all the hidden files.
================================================

## SYNOPSIS

    git secret clean [-v]


## DESCRIPTION
`git-secret-clean` - deletes all files in the current `git-secret` repo that end with `.secret`.

You can change the extension `git-secret` uses for encrypted files
with the `SECRETS_EXTENSION` environment variable.

Note that it will delete any files ending in `.secret`, even if they are not tracked by `git-secret`. 

Also note that this command does not delete unencrypted versions of files.

Verbose mode, enabled with the `-v` option, displays the filenames deleted.


## OPTIONS

    -v  - verbose mode, shows which files are deleted.
    -h  - shows this help.

You can also enable verbosity using the SECRETS_VERBOSE environment variable,
as documented at [git-secret(7)](https://git-secret.io/)

## MANUAL

Run `man git-secret-clean` to see this document.


## SEE ALSO

[git-secret-whoknows(1)](https://git-secret.io/git-secret-whoknows), [git-secret-add(1)](https://git-secret.io/git-secret-add),
[git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson)


================================================
FILE: man/man1/git-secret-hide.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-HIDE" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-hide\fR \- encrypts all added files with repo keyring\.
.
.SH "SYNOPSIS"
.
.nf

git secret hide [\-c] [\-F] [\-P] [\-v] [\-d] [\-m]
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-hide\fR \- writes an encrypted version of each file added by \fBgit\-secret\-add\fR command\.
.
.P
Then anyone enabled via \fBgit secret tell\fR can decrypt these files\.
.
.P
Under the hood, \fBgit\-secret\fR uses the keyring of public keys in \fB\.gitsecret/keys\fR to \fIencrypt\fR files, encrypted versions are typically called \fBfilename\.txt\.secret\fR\.
.
.P
Later permitted users can use their secret key (typically from their home directory) to \fIdecrypt\fR files\.
.
.P
It is recommended to encrypt (or re\-encrypt) all the files in a \fBgit\-secret\fR repo each time \fBgit secret hide\fR is run\.
.
.br
Otherwise the keyring (the one stored in \fB\.gitsecret/keys/*\.gpg\fR), may have changed since the last time the files were encrypted, and it\'s possible to create a state where the users in the output of \fBgit secret whoknows\fR may not be able to decrypt the some files in the repo, or may be able decrypt files they\'re not supposed to be able to\.
.
.P
In other words, unless you re\-encrypt all the files in a repo each time you \fBhide\fR any, it\'s possible to make it so some files can no longer be decrypted by users who should be (and would appear) able to decrypt them, and vice\-versa\.
.
.P
If you know what you are doing and wish to encrypt or re\-encrypt only a subset of the files even after reading the above paragraphs, you can use the \fB\-F\fR or \fB\-m\fR options\. The \fB\-F\fR option forces \fBgit secret hide\fR to skip any hidden files where the unencrypted versions aren\'t present\. The \fB\-m\fR option skips any hidden files that have not be been modified since the last time they were encrypted\.
.
.SH "OPTIONS"
.
.nf

\-v  \- verbose, shows extra information\.
\-c  \- deletes encrypted files before creating new ones\.
\-F  \- forces hide to continue if a file to encrypt is missing\.
\-P  \- preserve permissions of unencrypted file in encrypted file\.
\-d  \- deletes unencrypted files after encryption\.
\-m  \- encrypt files only when modified\.
\-h  \- shows help\.
.
.fi
.
.SH "ENV VARIABLES"
.
.IP "\(bu" 4
\fBSECRETS_GPG_COMMAND\fR changes the default \fBgpg\fR command to anything else
.
.IP "\(bu" 4
\fBSECRETS_GPG_ARMOR\fR is a boolean to enable \fB\-\-armor\fR mode \fIhttps://www\.gnupg\.org/gph/en/manual/r1290\.html\fR to store secrets in text format over binary
.
.IP "\(bu" 4
\fBSECRETS_DIR\fR changes the default \fB\.gitsecret/\fR folder to another name as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.IP "\(bu" 4
\fBSECRETS_EXTENSION\fR changes the default \fB\.secret\fR file extension
.
.IP "\(bu" 4
\fBSECRETS_VERBOSE\fR changes the output verbosity as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.IP "\(bu" 4
\fBSECRETS_PINENTRY\fR changes the \fBgpg \-\-pinentry\fR mode \fIhttps://github\.com/gpg/pinentry\fR as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.IP "" 0
.
.SH "MANUAL"
Run \fBman git\-secret\-hide\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-init(1) \fIhttps://git\-secret\.io/git\-secret\-init\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR


================================================
FILE: man/man1/git-secret-hide.1.md
================================================
git-secret-hide - encrypts all added files with repo keyring.
==================================================================

## SYNOPSIS

    git secret hide [-c] [-F] [-P] [-v] [-d] [-m]


## DESCRIPTION
`git-secret-hide`  - writes an encrypted version of each file added by `git-secret-add` command.

Then anyone enabled via `git secret tell` can decrypt these files. 

Under the hood, `git-secret` uses the keyring of public keys in `.gitsecret/keys` to _encrypt_ files,
encrypted versions are typically called `filename.txt.secret`.

Later permitted users can use their secret key (typically from their home directory) to _decrypt_ files.

It is recommended to encrypt (or re-encrypt) all the files in a `git-secret` repo each
time `git secret hide` is run.  
Otherwise the keyring (the one stored in `.gitsecret/keys/*.gpg`),
may have changed since the last time the files were encrypted, and it's possible
to create a state where the users in the output of `git secret whoknows`
may not be able to decrypt the some files in the repo, or may be able decrypt files
they're not supposed to be able to.

In other words, unless you re-encrypt all the files in a repo each time you `hide` any,
it's possible to make it so some files can no longer be decrypted by users who should be
(and would appear) able to decrypt them, and vice-versa.

If you know what you are doing and wish
to encrypt or re-encrypt only a subset of the files
even after reading the above paragraphs, you can use the `-F` or `-m` options.
The `-F` option forces `git secret hide` to skip any hidden files
where the unencrypted versions aren't present.
The `-m` option skips any hidden files that have
not be been modified since the last time they were encrypted.


## OPTIONS

    -v  - verbose, shows extra information.
    -c  - deletes encrypted files before creating new ones.
    -F  - forces hide to continue if a file to encrypt is missing.
    -P  - preserve permissions of unencrypted file in encrypted file.
    -d  - deletes unencrypted files after encryption.
    -m  - encrypt files only when modified.
    -h  - shows help.


## ENV VARIABLES

- `SECRETS_GPG_COMMAND` changes the default `gpg` command to anything else
- `SECRETS_GPG_ARMOR` is a boolean to enable [`--armor` mode](https://www.gnupg.org/gph/en/manual/r1290.html) to store secrets in text format over binary
- `SECRETS_DIR` changes the default `.gitsecret/` folder to another name as documented at [git-secret(7)](https://git-secret.io/)
- `SECRETS_EXTENSION` changes the default `.secret` file extension
- `SECRETS_VERBOSE` changes the output verbosity as documented at [git-secret(7)](https://git-secret.io/)
- `SECRETS_PINENTRY` changes the [`gpg --pinentry` mode](https://github.com/gpg/pinentry) as documented at [git-secret(7)](https://git-secret.io/)


## MANUAL

Run `man git-secret-hide` to see this document.


## SEE ALSO

[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),
[git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),
[git-secret-cat(1)](https://git-secret.io/git-secret-cat)


================================================
FILE: man/man1/git-secret-init.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-INIT" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-init\fR \- initializes git\-secret repository\.
.
.SH "SYNOPSIS"
.
.nf

git secret init
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-init\fR \- initializes a \fBgit\-secret\fR repo by setting up a \fB\.gitsecret\fR directory\.
.
.P
\fBgit\-secret\-init\fR should be run inside a \fBgit\fR repo, to create the \fB\.gitsecret\fR directory and initialize the repo for git\-secret\. Until a repository is initialized with \fBgit secret init\fR, all other \fBgit\-secret\fR commands are unavailable\.
.
.P
If a \fB\.gitsecret\fR directory already exists, \fBgit\-secret\-init\fR exits without making any changes\. Otherwise,
.
.IP "\(bu" 4
\fB\.gitignore\fR is modified to ignore \fBgit\-secret\fR\'s \fBrandom_seed_file\fR, and to not ignore \fB\.secret\fR files,
.
.IP "\(bu" 4
a \.gitsecret directory is created with the sub\-directories /keys and /paths,
.
.IP "\(bu" 4
The \fB\.gitsecret/keys\fR subdirectory permission is set to 700 to make gnupg happy\.
.
.IP "" 0
.
.P
See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information about renaming the \.gitsecret folder with the \fBSECRETS_DIR\fR environment variable, and changing the extension \fBgit\-secret\fR uses for secret files with the \fBSECRETS_EXTENSION\fR environment variable\.
.
.SH "OPTIONS"
.
.nf

\-h  \- shows this help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-init\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-usage(1) \fIhttps://git\-secret\.io/git\-secret\-usage\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR


================================================
FILE: man/man1/git-secret-init.1.md
================================================
git-secret-init - initializes git-secret repository.
====================================================

## SYNOPSIS

    git secret init


## DESCRIPTION
`git-secret-init` - initializes a `git-secret` repo by setting up a `.gitsecret` directory.

`git-secret-init` should be run inside a `git` repo, to create the 
`.gitsecret` directory and initialize the repo for git-secret.
Until a repository is initialized with `git secret init`, all other `git-secret` commands are unavailable.

If a `.gitsecret` directory already exists, `git-secret-init` exits without making any changes.
Otherwise, 

* `.gitignore` is modified to ignore `git-secret`'s `random_seed_file`,
and to not ignore `.secret` files,

* a .gitsecret directory is created with the sub-directories /keys and /paths,

* The `.gitsecret/keys` subdirectory permission is set to 700 to make gnupg happy.

See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret
folder with the `SECRETS_DIR` environment variable, and changing the extension `git-secret` uses for secret files
with the `SECRETS_EXTENSION` environment variable.


## OPTIONS

    -h  - shows this help.


## MANUAL

Run `man git-secret-init` to see this document.


## SEE ALSO

[git-secret-usage(1)](https://git-secret.io/git-secret-usage), [git-secret-tell(1)](https://git-secret.io/git-secret-tell)


================================================
FILE: man/man1/git-secret-list.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-LIST" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-list\fR \- prints all the added files\.
.
.SH "SYNOPSIS"
.
.nf

git secret list
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-list\fR \- print the files currently considered secret in this repo\.
.
.P
Shows tracked files from \fB\.gitsecret/paths/mapping\.cfg\fR\.
.
.P
(See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information about renaming the \.gitsecret folder using the \fBSECRETS_DIR\fR environment variable\.
.
.SH "OPTIONS"
.
.nf

\-h  \- shows this help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-list\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-whoknows(1) \fIhttps://git\-secret\.io/git\-secret\-whoknows\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-remove(1) \fIhttps://git\-secret\.io/git\-secret\-remove\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR


================================================
FILE: man/man1/git-secret-list.1.md
================================================
git-secret-list - prints all the added files.
=============================================

## SYNOPSIS

    git secret list


## DESCRIPTION
`git-secret-list` - print the files currently considered secret in this repo.

Shows tracked files from `.gitsecret/paths/mapping.cfg`.

(See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret
folder using the `SECRETS_DIR` environment variable.


## OPTIONS

    -h  - shows this help.


## MANUAL

Run `man git-secret-list` to see this document.


## SEE ALSO

[git-secret-whoknows(1)](https://git-secret.io/git-secret-whoknows), [git-secret-add(1)](https://git-secret.io/git-secret-add),
[git-secret-remove(1)](https://git-secret.io/git-secret-remove), [git-secret-hide(1)](https://git-secret.io/git-secret-hide),
[git-secret-reveal(1)](https://git-secret.io/git-secret-reveal), [git-secret-cat(1)](https://git-secret.io/git-secret-cat)


================================================
FILE: man/man1/git-secret-remove.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-REMOVE" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-remove\fR \- removes files from index\.
.
.SH "SYNOPSIS"
.
.nf

git secret remove [\-c] <pathspec>\.\.\.
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-remove\fR \- stops files from being tracked by \fBgit\-secret\fR\.
.
.P
This deletes filenames from \fB\.gitsecret/paths/mapping\.cfg\fR, which stops these files from being tracked by \fBgit\-secret\fR, and from being encrypted to, or decrypted from, \fB\.secret\fR encrypted versions\.
.
.P
There\'s also a \-c option to delete existing encrypted versions of the files provided\.
.
.P
Note unlike \fBadd\fR, which automatically add pathnames to \fB\.gitignore\fR, \fBremove\fR does not delete pathnames from \fB\.gitignore\fR\.
.
.P
(See git\-secret(7) \fIhttps://git\-secret\.io/git\-secret\fR for information about renaming the \.gitsecret folder using the \fBSECRETS_DIR\fR environment variable\.
.
.SH "OPTIONS"
.
.nf

\-c  \- deletes existing real encrypted files\.
\-h  \- shows help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-remove\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-clean(1) \fIhttps://git\-secret\.io/git\-secret\-clean\fR, git\-secret\-removeperson(1) \fIhttps://git\-secret\.io/git\-secret\-removeperson\fR


================================================
FILE: man/man1/git-secret-remove.1.md
================================================
git-secret-remove - removes files from index.
=============================================

## SYNOPSIS

    git secret remove [-c] <pathspec>...


## DESCRIPTION
`git-secret-remove` - stops files from being tracked by `git-secret`.

This deletes filenames from `.gitsecret/paths/mapping.cfg`, 
which stops these files from being tracked by `git-secret`, and from
being encrypted to, or decrypted from, `.secret` encrypted versions.

There's also a -c option to delete existing encrypted versions of the files provided.

Note unlike `add`, which automatically add pathnames to `.gitignore`, 
`remove` does not delete pathnames from `.gitignore`.

(See [git-secret(7)](https://git-secret.io/git-secret) for information about renaming the .gitsecret
folder using the `SECRETS_DIR` environment variable.


## OPTIONS

    -c  - deletes existing real encrypted files.
    -h  - shows help.


## MANUAL

Run `man git-secret-remove` to see this document.


## SEE ALSO

[git-secret-add(1)](https://git-secret.io/git-secret-add), [git-secret-clean(1)](https://git-secret.io/git-secret-clean),
[git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson)


================================================
FILE: man/man1/git-secret-removeperson.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-REMOVEPERSON" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-removeperson\fR \- removes user\'s public key from repo keyring\.
.
.SH "SYNOPSIS"
.
.nf

git secret removeperson <emails>\.\.\.
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-removeperson\fR \- removes public keys for passed email addresses from repo\'s \fBgit\-secret\fR keyring\.
.
.P
This command is used to begin the process of disallowing a user from encrypting and decrypting secrets with \fBgit\-secret\fR\.
.
.P
If you remove a user\'s access with \fBgit\-secret\-removeperson\fR, and then run \fBgit\-secret\-reveal\fR and \fBgit\-secret\-hide \-r\fR, that user will no longer be able user to decrypt the hidden files\.
.
.SH "OPTIONS"
.
.nf

\-h  \- shows this help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-removeperson\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-remove(1) \fIhttps://git\-secret\.io/git\-secret\-remove\fR, git\-secret\-clean(1) \fIhttps://git\-secret\.io/git\-secret\-clean\fR


================================================
FILE: man/man1/git-secret-removeperson.1.md
================================================
git-secret-removeperson - removes user's public key from repo keyring.
==================================================================================

## SYNOPSIS

    git secret removeperson <emails or fingerprints>...


## DESCRIPTION
`git-secret-removeperson` - removes public keys for passed email addresses or GPG fingerprints from repo's `git-secret` keyring.

This command is used to begin the process of disallowing a user from encrypting and decrypting secrets with `git-secret`.

If you remove a user's access with `git-secret-removeperson`, and then run `git-secret-reveal` and `git-secret-hide -r`,
that user will no longer be able user to decrypt the hidden files.


## OPTIONS

    -h  - shows this help.


## MANUAL

Run `man git-secret-removeperson` to see this document.


## SEE ALSO

[git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-remove(1)](https://git-secret.io/git-secret-remove),
[git-secret-clean(1)](https://git-secret.io/git-secret-clean)


================================================
FILE: man/man1/git-secret-reveal.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-REVEAL" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-reveal\fR \- decrypts all added files\.
.
.SH "SYNOPSIS"
.
.nf

git secret reveal [\-f] [\-F] [\-P] [\-v] [\-d dir] [\-p password] [pathspec]\.\.\.
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-reveal\fR \- decrypts passed files, or all files considered secret by \fBgit\-secret\fR\.
.
.P
Under the hood, \fBreveal\fR uses the \fBgpg \-\-decrypt\fR command and your private key (typically from your personal keyring in your home directory) to \fIdecrypt\fR files\.
.
.P
Therefore, for this operation to succeed, your personal keyring must contain a private key matching one of the public keys which were used to encrypt the secrets \-\- i\.e\., one of the public keys in your repo\'s \fBgit\-secret\fR keyring when the file was encrypted\.
.
.SH "OPTIONS"
.
.nf

\-f  \- forces gpg to overwrite existing files without prompt\.
\-F  \- forces reveal to continue even if a file fails to decrypt\.
\-d  \- specifies `\-\-homedir` option for the `gpg`, basically use this option if you store your keys in a custom location\.
\-v  \- verbose, shows extra information\.
\-p  \- specifies password for noinput mode, adds `\-\-passphrase` option for `gpg`\.
\-P  \- preserve permissions of encrypted file in unencrypted file\.
\-h  \- shows help\.
.
.fi
.
.SH "ENV VARIABLES"
.
.IP "\(bu" 4
\fBSECRETS_GPG_COMMAND\fR changes the default \fBgpg\fR command to anything else
.
.IP "\(bu" 4
\fBSECRETS_GPG_ARMOR\fR is a boolean to enable \fB\-\-armor\fR mode \fIhttps://www\.gnupg\.org/gph/en/manual/r1290\.html\fR to store secrets in text format over binary
.
.IP "\(bu" 4
\fBSECRETS_DIR\fR changes the default \fB\.gitsecret/\fR folder to another name as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.IP "\(bu" 4
\fBSECRETS_EXTENSION\fR changes the default \fB\.secret\fR file extension
.
.IP "\(bu" 4
\fBSECRETS_VERBOSE\fR changes the output verbosity as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.IP "\(bu" 4
\fBSECRETS_PINENTRY\fR changes the \fBgpg \-\-pinentry\fR mode \fIhttps://github\.com/gpg/pinentry\fR as documented at git\-secret(7) \fIhttps://git\-secret\.io/\fR
.
.IP "" 0
.
.SH "MANUAL"
Run \fBman git\-secret\-reveal\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-init(1) \fIhttps://git\-secret\.io/git\-secret\-init\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR


================================================
FILE: man/man1/git-secret-reveal.1.md
================================================
git-secret-reveal - decrypts all added files.
=============================================

## SYNOPSIS

    git secret reveal [-f] [-F] [-P] [-v] [-d dir] [-p password] [pathspec]...


## DESCRIPTION
`git-secret-reveal` - decrypts passed files, or all files considered secret by `git-secret`.

Under the hood, `reveal` uses the `gpg --decrypt` command
and your private key (typically from your personal keyring in your
home directory) to _decrypt_ files.

Therefore, for this operation to succeed, your personal keyring must contain a private key 
matching one of the public keys which were used to encrypt the secrets --
i.e., one of the public keys in your repo's `git-secret` keyring when the file was encrypted. 



## OPTIONS

    -f  - forces gpg to overwrite existing files without prompt.
    -F  - forces reveal to continue even if a file fails to decrypt.
    -d  - specifies `--homedir` option for the `gpg`, basically use this option if you store your keys in a custom location.
    -v  - verbose, shows extra information.
    -p  - specifies password for noinput mode, adds `--passphrase` option for `gpg`.
    -P  - preserve permissions of encrypted file in unencrypted file.
    -h  - shows help.


## ENV VARIABLES

- `SECRETS_GPG_COMMAND` changes the default `gpg` command to anything else
- `SECRETS_GPG_ARMOR` is a boolean to enable [`--armor` mode](https://www.gnupg.org/gph/en/manual/r1290.html) to store secrets in text format over binary
- `SECRETS_DIR` changes the default `.gitsecret/` folder to another name as documented at [git-secret(7)](https://git-secret.io/)
- `SECRETS_EXTENSION` changes the default `.secret` file extension
- `SECRETS_VERBOSE` changes the output verbosity as documented at [git-secret(7)](https://git-secret.io/)
- `SECRETS_PINENTRY` changes the [`gpg --pinentry` mode](https://github.com/gpg/pinentry) as documented at [git-secret(7)](https://git-secret.io/)


## MANUAL

Run `man git-secret-reveal` to see this document.


## SEE ALSO

[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-cat(1)](https://git-secret.io/git-secret-cat),
[git-secret-tell(1)](https://git-secret.io/git-secret-tell), [git-secret-add(1)](https://git-secret.io/git-secret-add),
[git-secret-hide(1)](https://git-secret.io/git-secret-hide)


================================================
FILE: man/man1/git-secret-tell.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-TELL" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-tell\fR \- adds person who can access private data\.
.
.SH "SYNOPSIS"
.
.nf

git secret tell [\-m] [\-d dir] [emails]\.\.\.
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret tell\fR \- adds user(s) to the list of those able to encrypt/decrypt secrets\.
.
.P
This lets the specified user encrypt new files, but will not immediately be able to decrypt existing files, which were encrypted without their key\. Files should be re\-encrypted with the new keyring by someone who already has access in order for the new user to be able to decrypt the files\.
.
.P
\fBgit\-secret tell\fR works only with email addresses, and will exit with an error if you have multiple keys in your keyring with specified email addresses, or if one of the specified emails is already associated with a key in the \fBgit\-secret\fR repo\'s keyring\.
.
.P
Under the hood, \fBgit\-secret\-tell\fR searches in the current user\'s \fBgnupg\fR keyring for public key(s) of passed email(s), then imports the corresponding public key(s) into your \fBgit\-secret\fR repo\'s keyring\.
.
.P
Versions of \fBgit\-secret tell\fR after \fB0\.3\.2\fR will warn about keys that are expired, revoked, or otherwise invalid\. It will also warn if multiple keys are found for a single email address\.
.
.P
\fBDo not manually import secret keys into \fBgit\-secret\fR\fR\. It won\'t work with imported secret keys anyway\.
.
.P
For more details about how \fBgit\-secret\fR uses public and private keys, see the documentation for \fBgit\-secret\-hide\fR and \fBgit\-secret\-reveal\fR\.
.
.SH "OPTIONS"
.
.nf

\-m  \- uses your current `git config user\.email` setting as an identifier for the key\.
\-d  \- specifies `\-\-homedir` option for `gpg`, basically use this option if your store your keys in a custom location\.
\-h  \- shows help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-tell\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-init(1) \fIhttps://git\-secret\.io/git\-secret\-init\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR, git\-secret\-removeperson(1) \fIhttps://git\-secret\.io/git\-secret\-removeperson\fR


================================================
FILE: man/man1/git-secret-tell.1.md
================================================
git-secret-tell - adds person who can access private data.
===============================================================

## SYNOPSIS

    git secret tell [-m] [-d dir] [emails or fingerprints]...


## DESCRIPTION
`git-secret tell` - adds user(s) to the list of those able to encrypt/decrypt secrets.

This lets the specified user encrypt new files,
but will not immediately be able to decrypt existing files, which were encrypted without their key.
Files should be re-encrypted with the new keyring by someone who already has access
in order for the new user to be able to decrypt the files.

`git-secret tell` works with email addresses or GPG key fingerprints, and will exit with an error if you have
multiple keys in your keyring with specified email addresses, or if one of the specified emails
is already associated with a key in the `git-secret` repo's keyring.

Under the hood, `git-secret-tell` searches in the current user's `gnupg` keyring for public key(s) of passed
email(s) or fingerprint(s), then imports the corresponding public key(s) into your `git-secret` repo's keyring.

Fingerprints should be specified as a hex string of 8 or more characters (e.g., full 40-character fingerprints).

Versions of `git-secret tell` after `0.3.2` will warn about keys that are expired, revoked, or otherwise invalid.
It will also warn if multiple keys are found for a single email address.

**Do not manually import secret keys into `git-secret`**. It won't work with imported secret keys anyway.

For more details about how `git-secret` uses public and private keys,
see the documentation for `git-secret-hide` and `git-secret-reveal`.

## OPTIONS

    -m  - uses your current `git config user.email` setting as an identifier for the key.
    -d  - specifies `--homedir` option for `gpg`, basically use this option if your store your keys in a custom location.
    -h  - shows help.


## MANUAL

Run `man git-secret-tell` to see this document.


## SEE ALSO

[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-add(1)](https://git-secret.io/git-secret-add),
[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),
[git-secret-cat(1)](https://git-secret.io/git-secret-cat), [git-secret-removeperson(1)](https://git-secret.io/git-secret-removeperson)


================================================
FILE: man/man1/git-secret-usage.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-USAGE" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-usage\fR \- prints all the available commands\.
.
.SH "SYNOPSIS"
.
.nf

git secret usage
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-usage\fR \- prints all the available \fBgit\-secret\fR commands\.
.
.SH "OPTIONS"
.
.nf

\-h  \- shows this help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-usage\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-init(1) \fIhttps://git\-secret\.io/git\-secret\-init\fR, git\-secret\-add(1) \fIhttps://git\-secret\.io/git\-secret\-add\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR


================================================
FILE: man/man1/git-secret-usage.1.md
================================================
git-secret-usage - prints all the available commands.
=====================================================

## SYNOPSIS

    git secret usage


## DESCRIPTION
`git-secret-usage` - prints all the available `git-secret` commands.


## OPTIONS

    -h  - shows this help.


## MANUAL

Run `man git-secret-usage` to see this document.


## SEE ALSO

[git-secret-init(1)](https://git-secret.io/git-secret-init), [git-secret-add(1)](https://git-secret.io/git-secret-add),
[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),
[git-secret-cat(1)](https://git-secret.io/git-secret-cat)


================================================
FILE: man/man1/git-secret-whoknows.1
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET\-WHOKNOWS" "1" "May 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\-whoknows\fR \- print email for each key in the keyring\.
.
.SH "SYNOPSIS"
.
.nf

git secret whoknows
.
.fi
.
.SH "DESCRIPTION"
\fBgit\-secret\-whoknows\fR \- print email addresses allowed to access the secrets in this repo\.
.
.SH "OPTIONS"
.
.nf

\-l  \- \'long\' output, shows key expiration dates\.
\-h  \- shows this help\.
.
.fi
.
.SH "MANUAL"
Run \fBman git\-secret\-whoknows\fR to see this document\.
.
.SH "SEE ALSO"
git\-secret\-list(1) \fIhttps://git\-secret\.io/git\-secret\-list\fR, git\-secret\-tell(1) \fIhttps://git\-secret\.io/git\-secret\-tell\fR, git\-secret\-hide(1) \fIhttps://git\-secret\.io/git\-secret\-hide\fR, git\-secret\-reveal(1) \fIhttps://git\-secret\.io/git\-secret\-reveal\fR, git\-secret\-cat(1) \fIhttps://git\-secret\.io/git\-secret\-cat\fR


================================================
FILE: man/man1/git-secret-whoknows.1.md
================================================
git-secret-whoknows - print email for each key in the keyring.
======================================================================

## SYNOPSIS

    git secret whoknows


## DESCRIPTION
`git-secret-whoknows` - print email addresses allowed to access the secrets in this repo.


## OPTIONS

    -l  - 'long' output, shows key expiration dates.
    -h  - shows this help.


## MANUAL

Run `man git-secret-whoknows` to see this document.


## SEE ALSO

[git-secret-list(1)](https://git-secret.io/git-secret-list), [git-secret-tell(1)](https://git-secret.io/git-secret-tell),
[git-secret-hide(1)](https://git-secret.io/git-secret-hide), [git-secret-reveal(1)](https://git-secret.io/git-secret-reveal),
[git-secret-cat(1)](https://git-secret.io/git-secret-cat)


================================================
FILE: man/man7/git-secret.7
================================================
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "GIT\-SECRET" "7" "June 2022" "sobolevn" "git-secret 0.5.1-alpha1"
.
.SH "NAME"
\fBgit\-secret\fR \- bash tool to store private data inside a git repo\.
.
.SH "Usage: Setting up git\-secret in a repository"
These steps cover the basic process of using \fBgit\-secret\fR to specify users and files that will interact with \fBgit\-secret\fR, and to encrypt and decrypt secrets\.
.
.IP "1." 4
Before starting, \fImake sure you have created a \fBgpg\fR RSA key\-pair\fR: which are a public key and a secret key pair, identified by your email address and stored with your gpg configuration\. Generally this gpg configuration and keys will be stored somewhere in your home directory\.
.
.IP "2." 4
Begin with an existing or new git repository\.
.
.IP "3." 4
Initialize the \fBgit\-secret\fR repository by running \fBgit secret init\fR\. The \fB\.gitsecret/\fR folder will be created, with subdirectories \fBkeys/\fR and \fBpaths/\fR, \fB\.gitsecret/keys/random_seed\fR will be added to \fB\.gitignore\fR, and \fB\.gitignore\fR will be configured to \fInot\fR ignore \fB\.secret\fR files\.
.
.IP "" 0
.
.P
\fBNote\fR all the contents of the \fB\.gitsecret/\fR folder should be checked in, \fB/except/\fR the \fBrandom_seed\fR file\. This also means that of all the files in \fB\.gitsecret/\fR, only the \fBrandom_seed\fR file should be mentioned in your \fB\.gitignore\fR file\.
.
.IP "1." 4
Add the first user to the \fBgit\-secret\fR repo keyring by running \fBgit secret tell your@email\.id\fR\.
.
.IP "2." 4
Now it\'s time to add files you wish to encrypt inside the \fBgit\-secret\fR repository\. This can be done by running \fBgit secret add <filenames\.\.\.>\fR command, which will also (as of 0\.2\.6) add entries to \fB\.gitignore\fR, stopping those files from being added or committed to the repo unencrypted\.
.
.IP "3." 4
Then run \fBgit secret hide\fR to encrypt the files you added with \fBgit secret add\fR\. The files will be encrypted with the public keys in your git\-secret repo\'s keyring, each corresponding to a user\'s email that you used with \fBtell\fR\.
.
.IP "" 0
.
.P
After using \fBgit secret hide\fR to encrypt your data, it is safe to commit your changes\. \fBNOTE:\fR It\'s recommended to add the \fBgit secret hide\fR command to your \fBpre\-commit\fR hook, so you won\'t miss any changes\.
.
.IP "1." 4
Later you can decrypt files with the \fBgit secret reveal\fR command, or print their contents to stdout with the \fBgit secret cat\fR command\. If you used a password on your GPG key (always recommended), it will ask you for your password\. And you\'re done!
.
.IP "" 0
.
.SS "Usage: Adding someone to a repository using git\-secret"
.
.IP "1." 4
\fIGet their \fBgpg\fR public\-key\fR\. \fBYou won\'t need their secret key\.\fR They can export their public key for you using a command like: \fBgpg \-\-armor \-\-export their@email\.id > public_key\.txt # \-\-armor here makes it ascii\fR
.
.IP "2." 4
Import this key into your \fBgpg\fR keyring (in \fB~/\.gnupg\fR or similar) by running \fBgpg \-\-import public_key\.txt\fR
.
.IP "3." 4
Now add this person to your secrets repo by running \fBgit secret tell their@email\.id\fR (this will be the email address associated with their public key)
.
.IP "4." 4
Now remove the other user\'s public key from your personal keyring with \fBgpg \-\-delete\-keys their@email\.id\fR
.
.IP "5." 4
The newly added user cannot yet read the encrypted files\. Now, re\-encrypt the files using \fBgit secret reveal; git secret hide \-d\fR, and then commit and push the newly encrypted files\. (The \-d options deletes the unencrypted file after re\-encrypting it)\. Now the newly added user will be able to decrypt the files in the repo using \fBgit\-secret reveal\fR\.
.
.IP "" 0
.
.P
Note that when you first add a user to a git\-secret repo, they will not be able to decrypt existing files until another user re\-encrypts the files with the new keyring\.
.
.P
If you do not want unexpected keys added, you can configure some server\-side security policy with the \fBpre\-receive\fR hook\.
.
.SS "Using gpg"
You can follow a quick \fBgpg\fR tutorial at devdungeon \fIhttps://www\.devdungeon\.com/content/gpg\-tutorial\fR\. Here are the most useful commands to get started:
.
.P
To generate a RSA key\-pair, run:
.
.IP "" 4
.
.nf

gpg \-\-gen\-key
.
.fi
.
.IP "" 0
.
.P
To export your public key, run:
.
.IP "" 4
.
.nf

gpg \-\-armor \-\-export your\.email@address\.com > public\-key\.gpg
.
.fi
.
.IP "" 0
.
.P
To import the public key of someone else (to share the secret with them for instance), run:
.
.IP "" 4
.
.nf

gpg \-\-import public\-key\.gpg
.
.fi
.
.IP "" 0
.
.P
To make sure you get the original public keys of the indicated persons, be sure to use a secure channel to transfer it, or use a service you trust, preferably one that uses encryption such as Keybase, to retrieve their public key\. Otherwise you could grant the wrong person access to your secrets by mistake!
.
.SS "Using git\-secret for Continuous Integration / Continuous Deployment (CI/CD)"
When using \fBgit\-secret\fR for CI/CD, you get the benefit that any deployment is necessarily done with the correct configuration, since it is collocated with the changes in your code\.
.
.P
One way of doing it is the following:
.
.IP "1." 4
\fIcreate a gpg key\fR for your CI/CD environment\. You can chose any name and email address you want: for instance \fBMyApp Example <myapp@example\.com>\fR if your app is called MyApp and your CI/CD provider is Example\. It is easier not to define a passphrase for that key\. However, if defining a passphrase is unavoidable, use a unique passphrase for the private key\.
.
.IP "2." 4
run \fBgpg \-\-armor \-\-export\-secret\-key myapp@example\.com\fR to get your private key value
.
.IP "3." 4
Create an env var on your CI/CD server \fBGPG_PRIVATE_KEY\fR and assign it the private key value\. If a passphrase has been setup for the private key, create another env var on the CI/CD server \fBGPG_PASSPHRASE\fR and assign it the passphrase of the private key\.
.
.IP "4." 4
Then write your Continuous Deployment build script\. For instance:
.
.IP "" 0
.
.IP "" 4
.
.nf

# As the first step: install git\-secret,
# see: https://git\-secret\.io/installation

# Create private key file
echo "$GPG_PRIVATE_KEY" > \./private_key\.gpg
# Import private key and avoid the "Inappropriate ioctl for device" error
gpg \-\-batch \-\-yes \-\-pinentry\-mode loopback \-\-import private_key\.gpg
# Reveal secrets without user interaction and with passphrase\. If no passphrase
# is created for the key, remove `\-p $GPG_PASSPHRASE`
git secret reveal \-p "$GPG_PASSPHRASE"
# carry on with your build script, secret files are available \.\.\.
.
.fi
.
.IP "" 0
.
.P
Note: your CI/CD might not allow you to create a multiline value\. In that case, you can export it on one line with
.
.IP "" 4
.
.nf

gpg \-\-armor \-\-export\-secret\-key myapp@example\.com | tr \'\en\' \',\'
.
.fi
.
.IP "" 0
.
.P
You can then create your private key file with:
.
.IP "" 4
.
.nf

echo "$GPG_PRIVATE_KEY" | tr \',\' \'\en\' > \./private_key\.gpg
.
.fi
.
.IP "" 0
.
.P
Also note: the \fBgpg\fR version on the CI/CD server \fBMUST INTEROPERATE\fR with the one used locally\. Otherwise, \fBgpg\fR decryption can fail, which leads to \fBgit secret reveal\fR reporting \fBcannot find decrypted version of file\fR error\. The best way to ensure this is to use the same version of gnupg on different systems\.
.
.SH "Environment Variables and Configuration"
You can configure the version of \fBgpg\fR used, or the extension your encrypted files use, to suit your workflow better\. To do so, just set the required variable to the value you need\. This can be done in your shell environment file or with each \fBgit\-secret\fR command\. See below, or the man page of \fBgit\-secret\fR for an explanation of the environment variables \fBgit\-secret\fR uses\.
.
.P
The settings available to be changed are:
.
.IP "\(bu" 4
\fB$SECRETS_VERBOSE\fR \- sets the verbose flag to on for all \fBgit\-secret\fR commands; is identical to using \fB\-v\fR on each command that supports it\.
.
.IP "\(bu" 4
\fB$SECRETS_GPG_COMMAND\fR \- sets the \fBgpg\fR alternatives, defaults to \fBgpg\fR\. It can be changed to \fBgpg\fR, \fBgpg2\fR, \fBpgp\fR, \fB/usr/local/gpg\fR or any other value\. After doing so rerun the tests to be sure that it won\'t break anything\. Tested with \fBgpg\fR and \fBgpg2\fR\.
.
.IP "\(bu" 4
\fB$SECRETS_GPG_ARMOR\fR \- sets the \fBgpg\fR \fB\-\-armor\fR mode \fIhttps://www\.gnupg\.org/gph/en/manual/r1290\.html\fR\. Can be set to \fB1\fR to store secrets file as text\. By default is \fB0\fR and store files as binaries\.
.
.IP "\(bu" 4
\fB$SECRETS_EXTENSION\fR \- sets the secret files extension, defaults to \fB\.secret\fR\. It can be changed to any valid file extension\.
.
.IP "\(bu" 4
\fB$SECRETS_DIR\fR \- sets the directory where \fBgit\-secret\fR stores its files, defaults to \fB\.gitsecret\fR\. It can be changed to any valid directory name\.
.
.IP "\(bu" 4
\fB$SECRETS_PINENTRY\fR \- allows user to specify a setting for \fBgpg\fR\'s \fB\-\-pinentry\fR option\. See \fBgpg\fR docs \fIhttps://github\.com/gpg/pinentry\fR for details about gpg\'s \fB\-\-pinentry\fR option\.
.
.IP "" 0
.
.SH "The <code>\.gitsecret</code> folder (can be overridden with <code>SECRETS_DIR</code>)"
This folder contains information about the files encrypted by git\-secret, and about which public/private key sets can access the encrypted data\.
.
.P
You can change the name of this directory using the SECRETS_DIR environment variable\.
.
.P
Use the various \fBgit\-secret\fR commands to manipulate the files in \fB\.gitsecret\fR, you should not change the data in these files directly\.
.
.P
Exactly which files exist in the \fB\.gitsecret\fR folder and what their contents are vary slightly across different versions of gpg\. Also, some versions of gpg might not work well with keyrings created or modified with newer versions of gpg\. Thus it is best to use git\-secret with the same version of gpg being used by all users\. This can be forced by installing matching versions of gpg and using \fBSECRETS_GPG_COMMAND\fR environment variable\.
.
.P
For example, there is an issue between \fBgpg\fR version 2\.1\.20 and later versions which can cause problems reading and writing keyring files between systems (this shows up in errors like \'gpg: skipped packet of type 12 in keybox\')\.
.
.P
This is not the only issue it is possible to encounter sharing files between different versions of \fBgpg\fR\. Generally you are most likely to encounter issues between \fBgpg\fR versions if you use \fBgit\-secret tell\fR or \fBgit\-secret removeperson\fR to modify your repo\'s \fBgit\-secret\fR keyring using a newer version of \fBgpg\fR, and then try to operate on that keyring using an older version of \fBgpg\fR\.
.
.P
The \fBgit\-secret\fR internal data is separated into two directories:
.
.SS "<code>\.gitsecret/paths</code>"
This directory currently contains only the file \fBmapping\.cfg\fR, which lists all the files git\-secret will consider secret\. In other words, the path mappings: what files are tracked to be hidden and revealed\.
.
.P
All other internal data used by git\-secret is stored in the directory:
.
.SS "<code>\.gitsecret/keys</code>"
This directory contains data used by \fBgit\-secret\fR and \fBgpg\fR to encrypt files to be accessed by the permitted users\.
.
.P
In particular, this directory contains a \fBgnupg keyring\fR with public keys for the emails used with \fBtell\fR\.
.
.P
This is the keyring used to encrypt files with \fBgit\-secret\-hide\fR\.
.
.P
\fBgit\-secret\-reveal\fR and \fBgit\-secret\-cat\fR, which decrypt secrets, instead use the user\'s \fIprivate keys\fR (which probably reside somewhere like ~/\.gnupg/)\. Note that user\'s private keys, needed for decryption, are \fInot\fR in the \fB\.gitsecret/keys\fR directory\.
.
.P
Generally speaking, all the files in this directory \fIexcept\fR \fBrandom_seed\fR should be checked into your repo\. By default, \fBgit secret init\fR will add the file \fB\.gitsecret/keys/random_seed\fR to your \fB\.gitignore\fR file\.
.
.P
Again, you can change the name of this directory using the SECRETS_DIR environment variable\.


================================================
FILE: man/man7/git-secret.7.md
================================================
git-secret - bash tool to store private data inside a git repo.
=============================================

## Usage: Setting up git-secret in a repository

These steps cover the basic process of using `git-secret`
to specify users and files that will interact with `git-secret`, 
and to encrypt and decrypt secrets.

0. Before starting, [make sure you have created a `gpg` RSA key-pair](#using-gpg): 
which are a public key and a secret key pair, identified by your email address and
stored with your gpg configuration.
Generally this gpg configuration and keys will be stored somewhere in your home directory.

1. Begin with an existing or new git repository. 

2. Initialize the `git-secret` repository by running `git secret init`. The `.gitsecret/` folder will be created,
with subdirectories `keys/` and `paths/`, 
`.gitsecret/keys/random_seed` will be added to `.gitignore`,
and `.gitignore` will be configured to _not_ ignore `.secret` files.

**Note** all the contents of the `.gitsecret/` folder should be checked in, **/except/** the `random_seed` file.
This also means that of all the files in `.gitsecret/`, only the `random_seed` file should be mentioned in your `.gitignore` file.

3. Add the first user to the `git-secret` repo keyring by running `git secret tell your@email.id`.

4. Now it's time to add files you wish to encrypt inside the `git-secret` repository.
This can be done by running `git secret add <filenames...>` command, which will also (as of 0.2.6) 
add entries to `.gitignore`, stopping those files from being added or committed to the repo unencrypted. 

5. Then run `git secret hide` to encrypt the files you added with `git secret add`.
The files will be encrypted with the public keys in your git-secret repo's keyring,
each corresponding to a user's email that you used with `tell`.

After using `git secret hide` to encrypt your data, it is safe to commit your changes.
**NOTE:** It's recommended to add the `git secret hide` command to your `pre-commit` hook, so you won't miss any changes.

6. Later you can decrypt files with the `git secret reveal` command, or print their contents to stdout with the
`git secret cat` command. If you used a password on your GPG key (always recommended), it will ask you for your password.
And you're done!

### Usage: Adding someone to a repository using git-secret

1. [Get their `gpg` public-key](#using-gpg). **You won't need their secret key.**
They can export their public key for you using a command like: 
`gpg --armor --export their@email.id > public_key.txt # --armor here makes it ascii`
 
2. Import this key into your `gpg` keyring (in `~/.gnupg` or similar) by running `gpg --import public_key.txt`

3. Now add this person to your secrets repo by running `git secret tell their@email.id`
(this will be the email address associated with their public key)

4. Now remove the other user's public key from your personal keyring with `gpg --delete-keys their@email.id`

5. The newly added user cannot yet read the encrypted files. Now, re-encrypt the files using
`git secret reveal; git secret hide -d`, and then commit and push the newly encrypted files.
(The -d options deletes the unencrypted file after re-encrypting it).
Now the newly added user will be able to decrypt the files in the repo using `git-secret reveal`.

Note that when you first add a user to a git-secret repo, they will not be able to decrypt existing files
until another user re-encrypts the files with the new keyring.  

If you do not
want unexpected keys added, you can configure some server-side security policy with the `pre-receive` hook.

### Using gpg

You can follow a quick `gpg` tutorial at [devdungeon](https://www.devdungeon.com/content/gpg-tutorial). Here are the most useful commands to get started:

To generate a RSA key-pair, run:

```shell
gpg --gen-key
```

To export your public key, run:

```shell
gpg --armor --export your.email@address.com > public-key.gpg
```

To import the public key of someone else (to share the secret with them for instance), run:

```shell
gpg --import public-key.gpg
```

To make sure you get the original public keys of the indicated persons, be sure to use a secure channel to transfer it, or use a service you trust, preferably one that uses encryption such as Keybase, to retrieve their public key. Otherwise you could grant the wrong person access to your secrets by mistake!

### Using git-secret for Continuous Integration / Continuous Deployment (CI/CD)

When using `git-secret` for CI/CD, you get the benefit that any deployment is necessarily done with the correct configuration, since it is collocated
with the changes in your code.

One way of doing it is the following:

1. [create a gpg key](#using-gpg) for your CI/CD environment. You can chose any name and email address you want: for instance `MyApp Example <myapp@example.com>`
if your app is called MyApp and your CI/CD provider is Example. It is easier not to define a passphrase for that key. However, if defining a passphrase is unavoidable, use a unique passphrase for the private key.
2. run `gpg --armor --export-secret-key myapp@example.com` to get your private key value
3. Create an env var on your CI/CD server `GPG_PRIVATE_KEY` and assign it the private key value. If a passphrase has been setup for the private key, create another env var on the CI/CD server `GPG_PASSPHRASE` and assign it the passphrase of the private key.
4. Then write your Continuous Deployment build script. For instance:

```shell
# As the first step: install git-secret,
# see: https://git-secret.io/installation

# Create private key file
echo "$GPG_PRIVATE_KEY" > ./private_key.gpg
# Import private key and avoid the "Inappropriate ioctl for device" error
gpg --batch --yes --pinentry-mode loopback --import private_key.gpg
# Reveal secrets without user interaction and with passphrase. If no passphrase
# is created for the key, remove `-p $GPG_PASSPHRASE`
git secret reveal -p "$GPG_PASSPHRASE"
# carry on with your build script, secret files are available ...
```

Note: your CI/CD might not allow you to create a multiline value. In that case, you can export it on one line with

```shell
gpg --armor --export-secret-key myapp@example.com | tr '\n' ','
```

You can then create your private key file with:

```shell
echo "$GPG_PRIVATE_KEY" | tr ',' '\n' > ./private_key.gpg
```

Also note: the `gpg` version on the CI/CD server **MUST INTEROPERATE** with the one used locally. Otherwise, `gpg` decryption can fail, which leads to `git secret reveal` reporting `cannot find decrypted version of file` error. The best way to ensure this is to use the same version of gnupg on different systems.

## Environment Variables and Configuration

You can configure the version of `gpg` used, or the extension your encrypted files use, to suit your workflow better.
To do so, just set the required variable to the value you need.
This can be done in your shell environment file or with each `git-secret` command.
See below, or the man page of `git-secret` for an explanation of the environment variables `git-secret` uses.

The settings available to be changed are:

* `$SECRETS_VERBOSE` - sets the verbose flag to on for all `git-secret` commands; is identical to using `-v` on each command that supports it.

* `$SECRETS_GPG_COMMAND` - sets the `gpg` alternatives, defaults to `gpg`.
It can be changed to `gpg`, `gpg2`, `pgp`, `/usr/local/gpg` or any other value.
After doing so rerun the tests to be sure that it won't break anything. Tested with `gpg` and `gpg2`.

* `$SECRETS_GPG_ARMOR` - sets the `gpg` [`--armor` mode](https://www.gnupg.org/gph/en/manual/r1290.html). Can be set to `1` to store secrets file as text. By default is `0` and store files as binaries.

* `$SECRETS_EXTENSION` - sets the secret files extension, defaults to `.secret`. It can be changed to any valid file extension.

* `$SECRETS_DIR` - sets the directory where `git-secret` stores its files, defaults to `.gitsecret`. It can be changed to any valid directory name.

* `$SECRETS_PINENTRY` - allows user to specify a setting for `gpg`'s `--pinentry` option. See [`gpg` docs](https://github.com/gpg/pinentry) for details about gpg's `--pinentry` option.

## The `.gitsecret` folder (can be overridden with `SECRETS_DIR`)

This folder contains information about the files encrypted by git-secret,
and about which public/private key sets can access the encrypted data.

You can change the name of this directory using the SECRETS_DIR environment variable.

Use the various `git-secret` commands to manipulate the files in `.gitsecret`,
you should not change the data in these files directly.

Exactly which files exist in the `.gitsecret` folder and what their contents are
vary slightly across different versions of gpg. Also, some versions of gpg
might not work well with keyrings created or modified with newer versions of gpg. 
Thus it is best to use git-secret with the same version of gpg being used by all users.
This can be forced by installing matching versions of gpg 
and using `SECRETS_GPG_COMMAND` environment variable.

For example, there is an issue between `gpg` version 2.1.20 and later versions
which can cause problems reading and writing keyring files between systems
(this shows up in errors like 'gpg: skipped packet of type 12 in keybox').

This is not the only issue it is possible to encounter sharing files between different versions
of `gpg`.
Generally you are most likely to encounter issues between `gpg`
versions if you use `git-secret tell` or `git-secret removeperson` to modify
your repo's `git-secret` keyring using a newer version of `gpg`, and then try to operate
on that keyring using an older version of `gpg`.

The `git-secret` internal data is separated into two directories:

### `.gitsecret/paths`

This directory currently contains only the file `mapping.cfg`, which lists all the files git-secret will consider secret.
In other words, the path mappings: what files are tracked to be hidden and revealed.

All other internal data used by git-secret is stored in the directory:

### `.gitsecret/keys`

This directory contains data used by `git-secret` and `gpg` to encrypt files to 
be accessed by the permitted users.

In particular, this directory contains a `gnupg keyring` with public keys for the emails used with `tell`.

This is the keyring used to encrypt files with `git-secret-hide`. 

`git-secret-reveal` and `git-secret-cat`, which decrypt secrets,
instead use the user's _private keys_ (which probably reside somewhere like ~/.gnupg/).
Note that user's private keys, needed for decryption, are _not_ in the `.gitsecret/keys` directory.

Generally speaking, all the files in this directory *except* `random_seed` should be checked into your repo.
By default, `git secret init` will add the file `.gitsecret/keys/random_seed` to your `.gitignore` file.

Again, you can change the name of this directory using the SECRETS_DIR environment variable.


================================================
FILE: src/_utils/_git_secret_tools.sh
================================================
#!/usr/bin/env bash

# Folders:
_SECRETS_DIR=${SECRETS_DIR:-".gitsecret"}
# if SECRETS_DIR env var is set, use that instead of .gitsecret
# for full path to secrets dir, use _get_secrets_dir()
# from _git_secret_tools.sh
_SECRETS_DIR_KEYS="${_SECRETS_DIR}/keys"
_SECRETS_DIR_PATHS="${_SECRETS_DIR}/paths"

# Files:
_SECRETS_DIR_KEYS_TRUSTDB="${_SECRETS_DIR_KEYS}/trustdb.gpg"

_SECRETS_DIR_PATHS_MAPPING="${_SECRETS_DIR_PATHS}/mapping.cfg"


# shellcheck disable=SC2153
if [[ -n "$SECRETS_VERBOSE" ]] && [[ "$SECRETS_VERBOSE" -ne 0 ]]; then
  # shellcheck disable=SC2034
  _SECRETS_VERBOSE='1'
  # _SECRETS_VERBOSE is empty or '1'. 
  # Empty means 'off', any other value means 'on'.
fi

: "${SECRETS_EXTENSION:=".secret"}"

# Commands:
: "${SECRETS_GPG_COMMAND:="gpg"}"
: "${SECRETS_CHECKSUM_COMMAND:="_os_based __sha256"}"
: "${SECRETS_OCTAL_PERMS_COMMAND:="_os_based __get_octal_perms"}"
: "${SECRETS_EPOCH_TO_DATE:="_os_based __epoch_to_date"}"

# Temp Dir:
: "${TMPDIR:=/tmp}"

# AWK scripts:
# shellcheck disable=SC2016
AWK_FSDB_HAS_RECORD='
BEGIN { FS=":"; OFS=":"; cnt=0; }
{
  if ( key == $1 )
  {
    cnt++
  }
}
END { if ( cnt > 0 ) print "0"; else print "1"; }
'

# shellcheck disable=SC2016
AWK_FSDB_RM_RECORD='
BEGIN { FS=":"; OFS=":"; }
{
  if ( key != $1 )
  {
    print $1,$2;
  }
}
'

# shellcheck disable=SC2016
AWK_FSDB_CLEAR_HASHES='
BEGIN { FS=":"; OFS=":"; }
{
  print $1,"";
}
'

# shellcheck disable=SC2016
AWK_GPG_VER_CHECK='
/^gpg/{
  version=$3
  n=split(version,array,".")
  if( n >= 2) {
    if(array[1] >= 2)
    {
      if(array[2] >= 1)
      {
        print 1
      }
      else
      {
        print 0
      }
    }
    else
    {
      print 0
    }
  }
  else if(array[1] >= 2)
  {
    print 1
  }
  else
  {
    print 0
  }
}
'

# This is 1 for gpg version 2.1 or greater, otherwise 0
GPG_VER_MIN_21="$($SECRETS_GPG_COMMAND --version | gawk "$AWK_GPG_VER_CHECK")"


# Bash:

# echos 0 if function exists, otherwise non-zero
function _function_exists {
  local function_name="$1" # required

  declare -f -F "$function_name" > /dev/null 2>&1
  echo $?
}


# OS based:

function _os_based {
  # Pass function name as first parameter.
  # It will be invoked as os-based function with the postfix.

  case "$(uname -s)" in

    Darwin)
      "$1_osx" "${@:2}"
    ;;

    Linux)
      "$1_linux" "${@:2}"
    ;;

    MINGW*)
      "$1_linux" "${@:2}"
    ;;

    MSYS*)
      "$1_linux" "${@:2}"
    ;;

    CYGWIN*)
      "$1_linux" "${@:2}"
    ;;

    FreeBSD)
      "$1_freebsd" "${@:2}"
    ;;

    # TODO: add MS Windows support.
    # MINGW32*|MSYS*)
    #   $1_ms ${@:2}
    # ;;

    *)
      _abort 'unsupported OS.'
    ;;
  esac
}


# File System:

function _clean_windows_path {
  # This function transforms windows paths to *nix paths
  # such as  c:\this\that.file -> /c/this/that/file
  # shellcheck disable=SC2001
  echo "$1" | sed 's#^\([a-zA-Z]\):/#/\1/#'
}


function _set_config {
  # This function creates a line in the config, or alters it.

  local key="$1" # required
  local value="$2" # required
  local filename="$3" # required

  # The exit status is 0 (true) if the name was found, 1 (false) if not:
  local contains
  contains=$(grep -Fq "$key" "$filename"; echo "$?")

  # Append or alter?
  if [[ "$contains" -eq 0 ]]; then
    _os_based __replace_in_file "$@"
  elif [[ "$contains" -eq 1 ]]; then
    echo "${key} = ${value}" >> "$filename"
  fi
}


# this sets the global variable 'temporary_filename'
# currently this function is only used by 'hide'
function _temporary_file {
  # This function creates temporary file
  # which will be removed on system exit.
  temporary_filename=$(_os_based __temp_file)  # is not `local` on purpose.

  trap 'if [[ -f "$temporary_filename" ]]; then if [[ -n "$_SECRETS_VERBOSE" ]] || [[ "$SECRETS_TEST_VERBOSE" == 1 ]]; then echo "git-secret: cleaning up: $temporary_filename"; fi; rm -f "$temporary_filename"; fi;' EXIT
}


# Helper function


function _gawk_inplace {
  local dest_file="${!#}"  # last argument

  _temporary_file

  gawk "$@" > "$temporary_filename"
  mv "$temporary_filename" "$dest_file"
}


# File System Database (fsdb):


function _get_record_filename {
  # Returns 1st field from passed record
  local record="$1"
  local filename
  filename=$(echo "$record" | awk -F: '{print $1}')

  echo "$filename"
}


function _get_record_hash {
  # Returns 2nd field from passed record
  local record="$1"
  local hash
  hash=$(echo "$record" | awk -F: '{print $2}')

  echo "$hash"
}


function _fsdb_has_record {
  # First parameter is the key
  # Second is the fsdb
  local key="$1"  # required
  local fsdb="$2" # required

  # 0 on contains, 1 for error.
  gawk -v key="$key" "$AWK_FSDB_HAS_RECORD" "$fsdb"
}


function _fsdb_rm_record {
  # First parameter is the key (filename)
  # Second is the path to fsdb
  local key="$1"  # required
  local fsdb="$2" # required

  _gawk_inplace -v "key=$key" "$AWK_FSDB_RM_RECORD" "$fsdb"
}


function _fsdb_clear_hashes {
  # First parameter is the path to fsdb
  local fsdb="$1" # required

  _gawk_inplace "$AWK_FSDB_CLEAR_HASHES" "$fsdb"
}


# Manuals:


function _show_manual_for {
  local function_name="$1" # required

  man "git-secret-${function_name}"
  exit 0
}


# Invalid options

function _invalid_option_for {
  local function_name="$1" # required

  man "git-secret-${function_name}"
  exit 1
}


# VCS:


function _check_ignore {
  local filename="$1" # required

  local result
  result="$(git check-ignore -q "$filename"; echo $?)"
  # returns 1 when not ignored, and 0 when ignored
  echo "$result"
}


function _git_normalize_filename {
  local filename="$1" # required

  local result
  result=$(git ls-files --full-name -o "$filename")
  echo "$result"
}


function _maybe_create_gitignore {
  # This function creates '.gitignore' if it was missing.

  local full_path
  full_path=$(_prepend_root_path '.gitignore')

  if [[ ! -f "$full_path" ]]; then
    touch "$full_path"
  fi
}


function _add_ignored_file {
  # This function adds a line with the filename into the '.gitignore' file.
  # It also creates '.gitignore' if it's not there

  local filename="$1" # required

  _maybe_create_gitignore

  local full_path
  full_path=$(_prepend_root_path '.gitignore')

  printf '%q\n' "$filename" >> "$full_path"
}


function _is_inside_git_tree {
  # Checks if we are working inside the `git` tree.
  local result
  result=$(git rev-parse --is-inside-work-tree > /dev/null 2>&1; echo $?)

  echo "$result"
}


function _is_tracked_in_git {
  local filename="$1" # required
  local result
  result="$(git ls-files --error-unmatch "$filename" >/dev/null 2>&1; echo $?)"

  if [[ "$result" -eq 0 ]]; then
    echo "1"
  else
    echo "0"
  fi
}


# This can give unexpected .git dir when used in a _subdirectory_
# of another git repo; See #431 and #433.
function _get_git_root_path {
  # We need this function to get the location of the `.git` folder,
  # since `.gitsecret` (or value set by SECRETS_DIR env var)
  # must be in the same dir.

  local result
  result=$(_clean_windows_path "$(git rev-parse --show-toplevel)")
  echo "$result"
}


# Relative paths:

function _prepend_root_path {
  # This function adds root path to any other path.

  local path="$1" # required

  local root_path
  root_path=$(_get_git_root_path)

  echo "$root_path/$path"
}


# if passed a name like 'filename.txt', returns a full path in the repo
# For #710: if we are in a subdir, fixup the path with the subdir
function _prepend_relative_root_path {
  local path="$1" # required

  local full_path
  full_path=$(_prepend_root_path "$path")

  local subdir
  subdir=$(git rev-parse --show-prefix)   # get the subdir of repo, like "subdir/"
  if [ -n "$subdir" ]; then
    full_path="$(dirname "$full_path")/${subdir}/$(basename "$full_path")"
  fi

  echo "$full_path"
}

function _get_secrets_dir {
  _prepend_root_path "${_SECRETS_DIR}"
}


function _get_secrets_dir_keys {
  _prepend_root_path "${_SECRETS_DIR_KEYS}"
}


function _get_secrets_dir_path {
  _prepend_root_path "${_SECRETS_DIR_PATHS}"
}


function _get_secrets_dir_keys_trustdb {
  _prepend_root_path "${_SECRETS_DIR_KEYS_TRUSTDB}"
}


function _get_secrets_dir_paths_mapping {
  _prepend_root_path "${_SECRETS_DIR_PATHS_MAPPING}"
}


# Logic:

function _message {
  local message="$1" # required
  echo "git-secret: $message"
}


function _abort {
  local message="$1" # required
  local exit_code=${2:-"1"}     # defaults to 1

  >&2 echo "git-secret: abort: $message"
  exit "$exit_code"
}


# _warn() sends warnings to stdout so user sees them
function _warn {
  local message="$1" # required

  >&2 echo "git-secret: warning: $message"
}


# _warn_or_abort "$error_message" "$exit_code" "$error_ok"
function _warn_or_abort {
  local message="$1"            # required
  local exit_code=${2:-"1"}     # defaults to 1
  local error_ok=${3:-0}        # can be 0 or 1

  if [[ "$error_ok" -eq "0" ]]; then
    if [[ "$exit_code" -eq "0" ]]; then
      # if caller sends an exit_code of 0, we change it to 1 before aborting.
      exit_code=1
    fi
    _abort "$message" "$exit_code"
  else
    _warn "$message" "$exit_code"
  fi
}


function _find_and_remove_secrets_formatted {
  local filenames
  _list_all_added_files # sets array variable 'filenames'

  for filename in "${filenames[@]}"; do
    local path # absolute path
    encrypted_filename=$(_get_encrypted_filename "$filename")
    if [[ -f "$encrypted_filename" ]]; then
      rm "$encrypted_filename"
      if [[ -n "$_SECRETS_VERBOSE" ]]; then
        echo "git-secret: deleted: $encrypted_filename"
      fi
    fi
  done
}



# this sets the global array variable 'filenames'
function _list_all_added_files {
  local path_mappings
  path_mappings=$(_get_secrets_dir_paths_mapping)

  if [[ ! -s "$path_mappings" ]]; then
    _abort "path_mappings file is missing or empty: $path_mappings"
  fi

  local filename
  filenames=()      # not local
  while read -r line; do
    filename=$(_get_record_filename "$line")
    filenames+=("$filename")
  done < "$path_mappings"

  declare -a filenames     # so caller can get list from filenames array
}


function _secrets_dir_exists {
  # This function checks if "$_SECRETS_DIR" exists and.

  local full_path
  full_path=$(_get_secrets_dir)

  if [[ ! -d "$full_path" ]]; then
    local name
    name=$(basename "$full_path")
    _abort "directory '$name' does not exist. Use 'git secret init' to initialize git-secret"
  fi
}


function _secrets_dir_is_not_ignored {
  # This function checks that "$_SECRETS_DIR" is not ignored.

  local git_secret_dir
  git_secret_dir=$(_get_secrets_dir)

  local ignores
  ignores=$(_check_ignore "$git_secret_dir")

  if [[ ! $ignores -eq 1 ]]; then
    _abort "entry already in .gitignore: $git_secret_dir"
  fi
}


function _exe_is_busybox {
  local exe
  exe="$1"

  # we assume stat is from busybox if it's a symlink
  local is_busybox=0
  local stat_path
  stat_path=$(command -v "$exe")
  if [ -L "$stat_path" ]; then
    is_busybox=1
  fi
  echo "$is_busybox"
}


# this is used by just about every command
function _user_required {
  # This function does a bunch of validations:
  # 1. It calls `_secrets_dir_exists` to verify that "$_SECRETS_DIR" exists.
  # 2. It ensures that "$_SECRETS_DIR_KEYS_TRUSTDB" exists.
  # 3. It ensures that there are added public keys.

  _secrets_dir_exists

  local trustdb
  trustdb=$(_get_secrets_dir_keys_trustdb)

  local error_message="no public keys for users found. run 'git secret tell email@address'."
  if [[ ! -f "$trustdb" ]]; then
    _abort "$error_message"
  fi

  local secrets_dir_keys
  secrets_dir_keys=$(_get_secrets_dir_keys)

  # for info about 3>&-
  # see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs 
  local keys_exist
  keys_exist=$($SECRETS_GPG_COMMAND --homedir "$secrets_dir_keys" --no-permission-warning -n --list-keys 3>&-)
  local exit_code=$?
  if [[ -z "$keys_exist" ]]; then
    _abort "$error_message"
  fi
  if [[ "$exit_code" -ne 0 ]]; then
    # this might catch corner case where gpg --list-keys shows
    # 'gpg: skipped packet of type 12 in keybox' warnings but succeeds?
    # See #136
    echo "$keys_exist"	# show whatever _did_ come out of gpg
    _abort "problem listing public keys with gpg: exit code $exit_code"
  fi
}


# note: this has the same 'username matching' issue described in
# https://github.com/sobolevn/git-secret/issues/268
# where it will match emails that have other emails as substrings.
# we need to use fingerprints for a unique key id with gpg.
function _get_user_key_expiry {
  # This function returns the user's key's expiry, as an epoch.
  # It will return the empty string
  # if there is no expiry date for the user's key
  local username="$1"
  local line

  local secrets_dir_keys
  secrets_dir_keys=$(_get_secrets_dir_keys)

  # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs
  line=$($SECRETS_GPG_COMMAND --homedir "$secrets_dir_keys" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode "$username" | grep ^pub: 3>&-)

  local expiry_epoch
  expiry_epoch=$(echo "$line" | cut -d: -f7)
  echo "$expiry_epoch"
}


function _assert_keyring_contains_emails {
  local homedir="$1"
  local keyring_name="$2"
  local emails="$3"

  # 1 here means 'expect $emails in keyring':
  _assert_keyring_emails "$homedir" "$keyring_name" "$emails" 1
}


function _assert_keyring_doesnt_contain_emails {
  local homedir="$1"
  local keyring_name="$2"
  local emails="$3"

  # 0 here means 'don't expect $emails in keyring':
  _assert_keyring_emails "$homedir" "$keyring_name" "$emails" 0
}

function _assert_keyring_contains_emails_at_least_once {
  local homedir=$1
  local keyring_name=$2
  local emails=$3
  _assert_keyring_emails "$homedir" "$keyring_name" "$emails" 1 1 # expect the email at least once in the keyring
}



function _is_gpg_fingerprint {
  # Returns 0 if the input looks like a GPG fingerprint or key ID
  # (8+ hex characters), 1 otherwise.
  local input="$1"
  local clean_input
  clean_input=$(echo "$input" | tr -d ' ')
  if [[ "$clean_input" =~ ^[A-Fa-f0-9]{8,}$ ]]; then
    return 0
  else
    return 1
  fi
}


function _check_fingerprint_in_keyring {
  # Checks if a key matching the given fingerprint exists in the keyring.
  # Returns 0 if found, 1 if not found.
  local homedir="$1"
  local fingerprint="$2"

  local args=()
  if [[ -n "$homedir" ]]; then
    args+=( "--homedir" "$homedir" )
  fi

  # 3>&- closes fd 3 for bats
  $SECRETS_GPG_COMMAND "${args[@]}" --no-permission-warning --list-keys "$fingerprint" > /dev/null 2>&1 3>&-
  return $?
}


function _assert_keyring_emails {
  local homedir="$1"
  local keyring_name="$2"
  local emails="$3"
  # set this to:
  # 0 to not expect the email in the keyring;
  # 1 to expect the email in the keyring
  local expected="$4"
  local allow_duplicates=$5 # set this to 0 to not allow duplicate emails in the keyring when processing assertion (optional)

  local gpg_uids
  gpg_uids=$(_get_users_in_gpg_keyring "$homedir")
  for email in "${emails[@]}"; do
    if _is_gpg_fingerprint "$email"; then
      # For fingerprints, check directly with gpg
      if [[ $expected -eq 1 ]]; then
        if ! _check_fingerprint_in_keyring "$homedir" "$email"; then
          _abort "no key found in gpg $keyring_name for fingerprint: $email"
        fi
      else
        if _check_fingerprint_in_keyring "$homedir" "$email"; then
          _abort "key already exists in gpg $keyring_name for fingerprint: $email"
        fi
      fi
    else
      if [[ $email != *"@"* ]]; then
        _abort "does not appear to be an email or fingerprint: $email"
      fi
      local emails_found=0
      for uid in $gpg_uids; do
        if [[ "$uid" == "$email" ]]; then
          emails_found=$((emails_found+1))
        fi
      done
      if [[ $expected -eq 1 ]]; then
          if [[ $emails_found -eq 0 ]]; then
            _abort "no key found in gpg $keyring_name for: $email"
          elif [[ $emails_found -gt 1 ]]; then
            if [[ $allow_duplicates -ne 1 ]]; then
              _abort "$emails_found keys found in gpg $keyring_name for: $email"
            fi
          fi
      else
          if [[ $emails_found -gt 0 ]]; then
            _abort "$emails_found keys found in gpg $keyring_name for: $email"
          fi
      fi
    fi

  done
}


function _get_encrypted_filename {
  local filename
  filename="$(dirname "$1")/$(basename "$1" "$SECRETS_EXTENSION")"
  echo "${filename}${SECRETS_EXTENSION}" | sed -e 's#^\./##'
}


# this is used throughout this file, and in 'whoknows'
function _get_users_in_gpg_keyring {
  # show the users in the gpg keyring.
  # `whoknows` command uses it internally.
  # parses the `gpg` public keys
  local homedir=$1
  local result
  local args=()
  if [[ -n "$homedir" ]]; then
    args+=( "--homedir" "$homedir" )
  fi

  ## We use --fixed-list-mode so older versions of gpg emit 'uid:' lines.
  ## Gawk splits on colon as --with-colon, matches field 1 as 'uid',
  result=$($SECRETS_GPG_COMMAND "${args[@]}" --no-permission-warning --list-public-keys --with-colon --fixed-list-mode | \
      gawk -F: '$1=="uid"' )

  local emails
  emails=$(_extract_emails_from_gpg_output "$result")

  # For #508 / #552: warn user if gpg indicates keys are one of:
  # i=invalid, d=disabled, r=revoked, e=expired, n=not valid
  # See https://github.com/gpg/gnupg/blob/master/doc/DETAILS#field-2---validity # for more on gpg 'validity codes'.
  local invalid_lines
  invalid_lines=$(echo "$result" | gawk -F: '$2=="i" || $2=="d" || $2=="r" || $2=="e" || $2=="n"')

  local emails_with_invalid_keys
  emails_with_invalid_keys=$(_extract_emails_from_gpg_output "$invalid_lines")

  if [[ -n "$emails_with_invalid_keys" ]]; then
     _warn "at least one key for email(s) is revoked, expired, or otherwise invalid: $emails_with_invalid_keys"
  fi

  echo "$emails"
}


function _extract_emails_from_gpg_output {
  local result=$1

  # gensub() outputs email from <> within field 10, "User-ID".  If there's no <>, then field is just an email address
  #  (and maybe a comment) and we pass it through.
  # Sed at the end removes any 'comment' that appears in parentheses, for #530
  # 3>&- closes fd 3 for bats, see https://github.com/bats-core/bats-core/blob/master/docs/source/writing-tests.md#file-descriptor-3-read-this-if-bats-hangs
  local emails
  emails=$(echo "$result" | gawk -F: '{print gensub(/.*<(.*)>.*/, "\\1", "g", $10); }' | sed 's/([^)]*)//g' 3>&-)
  echo "$emails"
}


function _get_users_in_gitsecret_keyring {
  # show the users in the gitsecret keyring.
  local secrets_dir_keys
  secrets_dir_keys=$(_get_secrets_dir_keys)

  local result
  result=$(_get_users_in_gpg_keyring "$secrets_dir_keys")

  echo "$result"
}


function _get_recipients {
  # This function is required to create an encrypted file for different users.
  # These users are called 'recipients' in the `gpg` terms.
  # It basically just parses the `gpg` public keys

  local result
  # put -r before each user:
  result=$(_get_users_in_gitsecret_keyring | sed 's/^/-r/')
  echo "$result"
}


function _decrypt {
  # required:
  local filename="$1"

  # optional:
  local write_to_file=${2:-1} # can be 0 or 1
  local force=${3:-0} # can be 0 or 1
  local homedir=${4:-""}
  local passphrase=${5:-""}
  local error_ok=${6:-0} # can be 0 or 1

  local encrypted_filename
  encrypted_filename=$(_get_encrypted_filename "$filename")

  if [ ! -f "$encrypted_filename" ]; then
    _warn_or_abort "cannot find file to decrypt: $encrypted_filename" "1" "$error_ok"
  else
    # we no longer use --no-permission-warning on decryption, for #811 
    local args=( "--use-agent" "--decrypt" )
  
    if [[ "$write_to_file" -eq 1 ]]; then
      args+=( "-o" "$filename" )
    fi
  
    if [[ "$force" -eq 1 ]]; then
      args+=( "--yes" )
    fi
  
    if [[ -n "$homedir" ]]; then
      args+=( "--homedir" "$homedir" )
    fi
  
    if [[ "$GPG_VER_MIN_21" -eq 1 ]]; then
      if [[ -n "$SECRETS_PINENTRY" ]]; then
        args+=( "--pinentry-mode" "$SECRETS_PINENTRY" )
      else
        args+=( "--pinentry-mode" "loopback" )
      fi
    fi

    if [[ -z "$_SECRETS_VERBOSE" ]]; then
      args+=( "--quiet" )
    fi

    set +e   # disable 'set -e' so we can capture exit_code
  
    #echo "# gpg passphrase: $passphrase" >&3
    local exit_code
    if [[ -n "$passphrase" ]]; then
      exec 5<<<"$passphrase"  # use 5, because descriptors 3 and 4 are used by bats
      $SECRETS_GPG_COMMAND "${args[@]}" --batch --yes --no-tty --passphrase-fd 5 "$encrypted_filename"
      exit_code=$?
      exec 5>&-   # close file descriptor 5
    else
      $SECRETS_GPG_COMMAND "${args[@]}" "$encrypted_filename"
      exit_code=$?
    fi
  
    set -e  # re-enable set -e
  
    # note that according to https://github.com/sobolevn/git-secret/issues/238 ,
    # it's possible for gpg to return a 0 exit code but not have decrypted the file
    #echo "# gpg exit code: $exit_code, error_ok: $error_ok" >&3
    if [[ "$exit_code" -ne "0" ]]; then
      local msg="problem decrypting file with gpg: exit code $exit_code: $filename"
      _warn_or_abort "$msg" "$exit_code" "$error_ok"
    fi
  fi

  # at this point the file should be written to disk or output to stdout
}


================================================
FILE: src/_utils/_git_secret_tools_freebsd.sh
================================================
#!/usr/bin/env bash

# support for freebsd. Mostly the same as MacOS.


# shellcheck disable=SC1117
function __replace_in_file_freebsd {
  sed -i.bak "s/^\($1[[:space:]]*=[[:space:]]*\).*\$/\1$2/" "$3"
}


function __temp_file_freebsd {
  local filename
  # man mktemp on FreeBSD:
  # ...
  # If	the -t prefix option is	given, mktemp will generate a template string
  #   based on the prefix and the TMPDIR	environment variable if	set.  The
  #   default location if TMPDIR	is not set is /tmp. "

  filename=$(mktemp -t _git_secret )
  echo "$filename";
}


function __sha256_freebsd {
  # this is in a different location than MacOS
  /usr/local/bin/shasum -a256 "$1"
}

function __get_octal_perms_freebsd {
  local filename
  filename=$1
  local perms
  perms=$(stat -f "%04OLp" "$filename")
  # perms is a string like '0644'.
  # In the "%04OLp':
  #   the '04' means 4 digits, 0 padded.  So we get 0644, not 644.
  #   the 'O' means Octal.
  #   the 'Lp' means 'low subfield of file type and permissions (st_mode).'
  #     (without 'L' you get 6 digits like '100644'.)
  echo "$perms"
}

function __epoch_to_date_freebsd {
  local epoch=$1;
  if [ -z "$epoch" ]; then
    echo ''
  else
    local cmd="date -I -r $epoch"
    #echo "# running: $cmd" >&3
    local datetime
    datetime=$($cmd)
    echo "$datetime"
  fi
}


================================================
FILE: src/_utils/_git_secret_tools_linux.sh
================================================
#!/usr/bin/env bash


# shellcheck disable=SC1117
function __replace_in_file_linux {
  sed -i.bak "s/^\($1\s*=\s*\).*\$/\1$2/" "$3"
}


function __temp_file_linux {
  local filename
  # man mktemp on CentOS 7:
  # mktemp [OPTION]... [TEMPLATE]
  # ...
  #  -p DIR, --tmpdir[=DIR]
  #        interpret TEMPLATE relative to DIR; if DIR is not specified,
  #        use $TMPDIR if set, else /tmp.  With this option, TEMPLATE
  #        must not be an absolute name; unlike  with -t, TEMPLATE may
  #        contain slashes, but mktemp creates only the final component
  # ...
  #  -t     interpret TEMPLATE as a single file name component,
  #         relative to a directory: $TMPDIR, if set; else the directory
  #         specified via -p; else /tmp [deprecated]

  filename=$(mktemp -p "${TMPDIR}" _git_secret.XXXXXX )
  # makes a filename like /$TMPDIR/_git_secret.ONIHo
  echo "$filename"
}

function __sha256_linux {
  sha256sum "$1"
}

function __get_octal_perms_linux {
  local filename
  filename=$1

  local stat_is_busybox
  stat_is_busybox=$(_exe_is_busybox "stat")
  local perms   # a string like '644'
  if [ "$stat_is_busybox" -eq 1 ]; then
    # special case for busybox, which doesn't understand --format
    perms=$(stat -c '%a' "$filename")
  else
    perms=$(stat --format '%a' "$filename")
  fi
  echo "$perms"
}

function __epoch_to_date_linux {
  local epoch=$1;
  if [ -z "$epoch" ]; then
    echo ''
  else
    local cmd="date +%F -d @$epoch"
    local datetime
    datetime=$($cmd)
    echo "$datetime"
  fi
}


================================================
FILE: src/_utils/_git_secret_tools_osx.sh
================================================
#!/usr/bin/env bash


# shellcheck disable=SC1117
function __replace_in_file_osx {
  sed -i.bak "s/^\($1[[:space:]]*=[[:space:]]*\).*\$/\1$2/" "$3"
}


function __temp_file_osx {
  local filename
  # man mktemp on OSX:
  # ...
  # "If the -t prefix option is given, mktemp will generate a template string
  #   based on the prefix and the _CS_DARWIN_USER_TEMP_DIR configuration vari-
  #   able if available.  Fallback locations if _CS_DARWIN_USER_TEMP_DIR is not
  #   available are TMPDIR and /tmp."

  # we use /usr/bin/mktemp in case there's another mktemp available. See #485
  filename=$(/usr/bin/mktemp -t _git_secret )
  # On OSX this can make a filename like
  # '/var/folders/nz/vv4_91234569k3tkvyszvwg90009gn/T/_git_secret.HhvUPlUI'
  echo "$filename";
}


function __sha256_osx {
  /usr/bin/shasum -a256 "$1"
}

function __get_octal_perms_osx {
  local filename
  filename=$1
  local perms
  # we use /usr/bin/stat in case there's another stat available from brew. See #918
  perms=$(/usr/bin/stat -f "%04OLp" "$filename")
  # see _git_secret_tools_freebsd.sh for more about stat's format string
  echo "$perms"
}

function __epoch_to_date_osx {
  local epoch=$1;
  if [ -z "$epoch" ]; then
    echo ''
  else
    #date -r 234234234 +"%Y-%m-%d"
    local datetime
    datetime=$(date -r "$epoch" +'%Y-%m-%d')
    echo "$datetime"
  fi
}



================================================
FILE: src/commands/git_secret_add.sh
================================================
#!/usr/bin/env bash


function add {
  OPTIND=1

  while getopts "ihv" opt; do
    case "$opt" in
      i) ;;    # this doesn't change anything

      h) _show_manual_for "add";;

      v) _SECRETS_VERBOSE=1;;

      *) _invalid_option_for "add";;
    esac
  done

  shift $((OPTIND-1))
  [ "$1" = "--" ] && shift

  _user_required

  # Checking if all files are correct (ignored and inside the repo):

  local not_ignored=()
  local items=( "$@" )

  # Checking if all files in options are ignored:
  for item in "${items[@]}"; do
    local path # absolute path
    local normalized_path # relative to the .git dir
    normalized_path=$(_git_normalize_filename "$item")
    path=$(_prepend_root_path "$normalized_path")

    # check that the file is not tracked
    local in_git
    in_git=$(_is_tracked_in_git "$item")
    if [[ "$in_git" -ne 0  ]]; then
       _abort "file tracked in git, consider using 'git rm --cached $item'"
    fi

    # Checking that file is valid:
    if [[ ! -f "$path" ]]; then
      _abort "file not found: $item"
    fi

    # Checking that it is ignored:
    local ignored
    ignored=$(_check_ignore "$path")

    if [[ "$ignored" -ne 0 ]]; then
      # Collect unignored files:
      not_ignored+=("$normalized_path")
    fi
  done

  # Are there any unignored files?

  if [[ ! "${#not_ignored[@]}" -eq 0 ]]; then
    # Add these files to `.gitignore` automatically:
    # see https://github.com/sobolevn/git-secret/issues/18 for more.

    for item in "${not_ignored[@]}"; do
      _message "file not in .gitignore, adding: $item"
      _add_ignored_file "$item"
    done
  fi

  # Adding files to path mappings:

  local fsdb
  fsdb=$(_get_secrets_dir_paths_mapping)
  local count
  count=0

  for item in "${items[@]}"; do
    local path
    local key
    path=$(_git_normalize_filename "$item")
    key="$path"

    # Adding files into system, skipping duplicates.
    local already_in
    already_in=$(_fsdb_has_record "$key" "$fsdb")
    if [[ "$already_in" -eq 1 ]]; then
      echo "$key" >> "$fsdb"
       if [[ -n "$_SECRETS_VERBOSE" ]]; then
        _message "adding file: $key"
      fi

      ((count=count+1))
    fi
  done

  _message "$count item(s) added."
}


================================================
FILE: src/commands/git_secret_cat.sh
================================================
#!/usr/bin/env bash


function cat {
  local homedir=''
  local passphrase=''

  OPTIND=1

  while getopts 'hd:p:' opt; do
    case "$opt" in
      h) _show_manual_for 'cat';;

      p) passphrase=$OPTARG;;

      d) homedir=$(_clean_windows_path "$OPTARG");;

      *) _invalid_option_for 'cat';;
    esac
  done

  shift $((OPTIND-1))
  [ "$1" = '--' ] && shift

  _user_required

  # Command logic:

  for line in "$@"
  do
    local filename
    local path

    filename=$(_get_record_filename "$line")
    path=$(_prepend_relative_root_path "$filename")  # this uses the _relative version because of #710

    # The parameters are: filename, write-to-file, force, homedir, passphrase
    _decrypt "$path" "0" "0" "$homedir" "$passphrase"
  done
}


================================================
FILE: src/commands/git_secret_changes.sh
================================================
#!/usr/bin/env bash

function changes {
  local passphrase=""

  OPTIND=1

  while getopts 'hd:p:' opt; do
    case "$opt" in
      h) _show_manual_for 'changes';;

      p) passphrase=$OPTARG;;

      d) homedir=$(_clean_windows_path "$OPTARG");;

      *) _invalid_option_for 'changes';;
    esac
  done

  shift $((OPTIND-1))
  [
Download .txt
gitextract_322qge9w/

├── .ci/
│   ├── docker-ci/
│   │   ├── alma/
│   │   │   └── Dockerfile
│   │   ├── alpine/
│   │   │   └── Dockerfile
│   │   ├── arch/
│   │   │   └── Dockerfile
│   │   ├── debian-gnupg1/
│   │   │   └── Dockerfile
│   │   ├── debian-gnupg2/
│   │   │   └── Dockerfile
│   │   ├── fedora/
│   │   │   └── Dockerfile
│   │   ├── rocky/
│   │   │   └── Dockerfile
│   │   └── ubuntu/
│   │       └── Dockerfile
│   ├── github_release_script.sh
│   ├── release-ci/
│   │   ├── alma/
│   │   │   └── Dockerfile
│   │   ├── alpine/
│   │   │   └── Dockerfile
│   │   ├── debian/
│   │   │   └── Dockerfile
│   │   ├── fedora/
│   │   │   └── Dockerfile
│   │   ├── rocky/
│   │   │   └── Dockerfile
│   │   └── ubuntu/
│   │       └── Dockerfile
│   └── releaser/
│       └── alpine/
│           └── Dockerfile
├── .editorconfig
├── .gitattributes
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── dependabot.yml
│   └── workflows/
│       ├── build-man.yml
│       ├── github-pages.yml
│       ├── release-ci.yml
│       ├── release.yml
│       └── test.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE.md
├── Makefile
├── README.md
├── RFC/
│   └── RFC001.md
├── docs/
│   ├── Gemfile
│   ├── _config.yml
│   ├── _includes/
│   │   ├── favicons.html
│   │   ├── footer.html
│   │   ├── head.html
│   │   ├── header.html
│   │   ├── icon-github.html
│   │   ├── icon-twitter.html
│   │   └── why.md
│   ├── _layouts/
│   │   ├── default.html
│   │   ├── page.html
│   │   └── post.html
│   ├── _sass/
│   │   ├── _base.scss
│   │   ├── _layout.scss
│   │   └── _syntax-highlighting.scss
│   ├── build.sh
│   ├── css/
│   │   └── main.scss
│   ├── feed.xml
│   ├── images/
│   │   └── favicons/
│   │       ├── browserconfig.xml
│   │       └── manifest.json
│   ├── index.html
│   ├── installation.md
│   └── plugins.md
├── man/
│   ├── man1/
│   │   ├── git-secret-add.1
│   │   ├── git-secret-add.1.md
│   │   ├── git-secret-cat.1
│   │   ├── git-secret-cat.1.md
│   │   ├── git-secret-changes.1
│   │   ├── git-secret-changes.1.md
│   │   ├── git-secret-clean.1
│   │   ├── git-secret-clean.1.md
│   │   ├── git-secret-hide.1
│   │   ├── git-secret-hide.1.md
│   │   ├── git-secret-init.1
│   │   ├── git-secret-init.1.md
│   │   ├── git-secret-list.1
│   │   ├── git-secret-list.1.md
│   │   ├── git-secret-remove.1
│   │   ├── git-secret-remove.1.md
│   │   ├── git-secret-removeperson.1
│   │   ├── git-secret-removeperson.1.md
│   │   ├── git-secret-reveal.1
│   │   ├── git-secret-reveal.1.md
│   │   ├── git-secret-tell.1
│   │   ├── git-secret-tell.1.md
│   │   ├── git-secret-usage.1
│   │   ├── git-secret-usage.1.md
│   │   ├── git-secret-whoknows.1
│   │   └── git-secret-whoknows.1.md
│   └── man7/
│       ├── git-secret.7
│       └── git-secret.7.md
├── src/
│   ├── _utils/
│   │   ├── _git_secret_tools.sh
│   │   ├── _git_secret_tools_freebsd.sh
│   │   ├── _git_secret_tools_linux.sh
│   │   └── _git_secret_tools_osx.sh
│   ├── commands/
│   │   ├── git_secret_add.sh
│   │   ├── git_secret_cat.sh
│   │   ├── git_secret_changes.sh
│   │   ├── git_secret_clean.sh
│   │   ├── git_secret_hide.sh
│   │   ├── git_secret_init.sh
│   │   ├── git_secret_list.sh
│   │   ├── git_secret_remove.sh
│   │   ├── git_secret_removeperson.sh
│   │   ├── git_secret_reveal.sh
│   │   ├── git_secret_tell.sh
│   │   ├── git_secret_usage.sh
│   │   └── git_secret_whoknows.sh
│   ├── main.sh
│   └── version.sh
├── tests/
│   ├── _test_base.bash
│   ├── fixtures/
│   │   └── gpg/
│   │       ├── README.md
│   │       ├── attacker1@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user1@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user2@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user3@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       ├── user4@gitsecret.io/
│   │       │   ├── private.key
│   │       │   └── public.key
│   │       └── user5@gitsecret.io/
│   │           ├── private.key
│   │           └── public.key
│   ├── test_add.bats
│   ├── test_cat.bats
│   ├── test_changes.bats
│   ├── test_clean.bats
│   ├── test_expiration.bats
│   ├── test_hide.bats
│   ├── test_hide_continue.bats
│   ├── test_init.bats
│   ├── test_list.bats
│   ├── test_main.bats
│   ├── test_make_install.bats
│   ├── test_noname.bats
│   ├── test_remove.bats
│   ├── test_removeperson.bats
│   ├── test_reveal.bats
│   ├── test_reveal_filename.bats
│   ├── test_tell.bats
│   ├── test_usage.bats
│   └── test_whoknows.bats
├── utils/
│   ├── apk/
│   │   ├── build.sh
│   │   ├── deploy.sh
│   │   ├── install.sh
│   │   ├── meta.sh
│   │   └── nfpm.yml
│   ├── build-utils.sh
│   ├── deb/
│   │   ├── build.sh
│   │   ├── deploy.sh
│   │   └── install.sh
│   ├── install.sh
│   ├── rpm/
│   │   ├── build.sh
│   │   ├── deploy.sh
│   │   ├── git-secret.repo
│   │   └── install.sh
│   ├── tests.sh
│   └── uninstall.sh
└── vendor/
    ├── README.md
    └── bats-core/
        ├── .devcontainer/
        │   ├── Dockerfile
        │   └── devcontainer.json
        ├── .editorconfig
        ├── .gitattributes
        ├── .github/
        │   ├── ISSUE_TEMPLATE/
        │   │   ├── bug_report.md
        │   │   └── feature_request.md
        │   └── workflows/
        │       ├── check_pr_label.sh
        │       ├── release.yml
        │       ├── release_dockerhub.yml
        │       └── tests.yml
        ├── .gitignore
        ├── .readthedocs.yml
        ├── AUTHORS
        ├── Dockerfile
        ├── LICENSE.md
        ├── README.md
        ├── bin/
        │   └── bats
        ├── contrib/
        │   ├── release.sh
        │   ├── rpm/
        │   │   └── bats.spec
        │   └── semver
        ├── docker/
        │   ├── install_tini.sh
        │   └── tini.pubkey.gpg
        ├── docker-compose.override.dist
        ├── docker-compose.yml
        ├── docs/
        │   ├── .markdownlint.json
        │   ├── CHANGELOG.md
        │   ├── CODEOWNERS
        │   ├── CODE_OF_CONDUCT.md
        │   ├── CONTRIBUTING.md
        │   ├── Makefile
        │   ├── PULL_REQUEST_TEMPLATE.md
        │   ├── examples/
        │   │   ├── README.md
        │   │   ├── package-tarball
        │   │   └── package-tarball.bats
        │   ├── make.bat
        │   ├── releasing.md
        │   ├── source/
        │   │   ├── _static/
        │   │   │   └── .gitkeep
        │   │   ├── _templates/
        │   │   │   └── .gitkeep
        │   │   ├── conf.py
        │   │   ├── docker-usage.md
        │   │   ├── faq.rst
        │   │   ├── gotchas.rst
        │   │   ├── index.rst
        │   │   ├── installation.rst
        │   │   ├── requirements.txt
        │   │   ├── tutorial.rst
        │   │   ├── usage.md
        │   │   └── writing-tests.md
        │   └── versions.md
        ├── install.sh
        ├── lib/
        │   └── bats-core/
        │       ├── common.bash
        │       ├── formatter.bash
        │       ├── preprocessing.bash
        │       ├── semaphore.bash
        │       ├── test_functions.bash
        │       ├── tracing.bash
        │       └── validator.bash
        ├── libexec/
        │   └── bats-core/
        │       ├── bats
        │       ├── bats-exec-file
        │       ├── bats-exec-suite
        │       ├── bats-exec-test
        │       ├── bats-format-cat
        │       ├── bats-format-junit
        │       ├── bats-format-pretty
        │       ├── bats-format-tap
        │       ├── bats-format-tap13
        │       └── bats-preprocess
        ├── man/
        │   ├── Makefile
        │   ├── README.md
        │   ├── bats.1
        │   ├── bats.1.ronn
        │   ├── bats.7
        │   └── bats.7.ronn
        ├── package.json
        ├── shellcheck.sh
        ├── test/
        │   ├── bats.bats
        │   ├── concurrent-coordination.bash
        │   ├── file_setup_teardown.bats
        │   ├── fixtures/
        │   │   ├── bats/
        │   │   │   ├── BATS_TMPDIR.bats
        │   │   │   ├── cmd_using_stdin.bash
        │   │   │   ├── comment_style.bats
        │   │   │   ├── dos_line_no_shellcheck.bats
        │   │   │   ├── duplicate-tests_no_shellcheck.bats
        │   │   │   ├── empty.bats
        │   │   │   ├── environment.bats
        │   │   │   ├── evaluation_count/
        │   │   │   │   ├── file1.bats
        │   │   │   │   └── file2.bats
        │   │   │   ├── expand_var_in_test_name.bats
        │   │   │   ├── exported_function.bats
        │   │   │   ├── external_function_calls.bats
        │   │   │   ├── external_functions.bash
        │   │   │   ├── external_functions.bats
        │   │   │   ├── failing.bats
        │   │   │   ├── failing_and_passing.bats
        │   │   │   ├── failing_helper.bats
        │   │   │   ├── failing_setup.bats
        │   │   │   ├── failing_teardown.bats
        │   │   │   ├── failing_with_bash_cond.bats
        │   │   │   ├── failing_with_bash_expression.bats
        │   │   │   ├── failing_with_negated_command.bats
        │   │   │   ├── failure_in_free_code.bats
        │   │   │   ├── hang_after_run.bats
        │   │   │   ├── hang_in_run.bats
        │   │   │   ├── hang_in_setup_file.bats
        │   │   │   ├── hang_in_teardown.bats
        │   │   │   ├── hang_in_teardown_file.bats
        │   │   │   ├── hang_in_test.bats
        │   │   │   ├── intact.bats
        │   │   │   ├── issue-205.bats
        │   │   │   ├── issue-433/
        │   │   │   │   ├── repro1.bats
        │   │   │   │   └── repro2.bats
        │   │   │   ├── issue-519.bats
        │   │   │   ├── load.bats
        │   │   │   ├── loop_keep_IFS.bats
        │   │   │   ├── no-final-newline.bats
        │   │   │   ├── output.bats
        │   │   │   ├── parallel.bats
        │   │   │   ├── passing.bats
        │   │   │   ├── passing_and_failing.bats
        │   │   │   ├── passing_and_skipping.bats
        │   │   │   ├── passing_failing_and_skipping.bats
        │   │   │   ├── print_output_on_failure.bats
        │   │   │   ├── quoted_and_unquoted_test_names_no_shellcheck.bats
        │   │   │   ├── read_from_stdin.bats
        │   │   │   ├── reference_unset_parameter.bats
        │   │   │   ├── reference_unset_parameter_in_setup.bats
        │   │   │   ├── reference_unset_parameter_in_teardown.bats
        │   │   │   ├── run_long_command.bats
        │   │   │   ├── set_-eu_in_setup_and_teardown.bats
        │   │   │   ├── setup.bats
        │   │   │   ├── show-output-of-passing-tests.bats
        │   │   │   ├── single_line_no_shellcheck.bats
        │   │   │   ├── skipped.bats
        │   │   │   ├── skipped_with_parens.bats
        │   │   │   ├── source_nonexistent_file.bats
        │   │   │   ├── source_nonexistent_file_in_setup.bats
        │   │   │   ├── source_nonexistent_file_in_teardown.bats
        │   │   │   ├── tab in filename.bats
        │   │   │   ├── teardown.bats
        │   │   │   ├── test_helper.bash
        │   │   │   ├── unbound_variable.bats
        │   │   │   ├── unofficial_bash_strict_mode.bash
        │   │   │   ├── unofficial_bash_strict_mode.bats
        │   │   │   ├── update_path_env.bats
        │   │   │   ├── verbose-run.bats
        │   │   │   ├── whitespace_no_shellcheck.bats
        │   │   │   └── without_trailing_newline.bats
        │   │   ├── file_setup_teardown/
        │   │   │   ├── no_setup_file.bats
        │   │   │   ├── no_teardown_file.bats
        │   │   │   ├── setup_file.bats
        │   │   │   ├── setup_file2.bats
        │   │   │   ├── setup_file_does_not_leak_env.bats
        │   │   │   ├── setup_file_does_not_leak_env2.bats
        │   │   │   ├── setup_file_even_if_all_tests_are_skipped.bats
        │   │   │   ├── setup_file_failed.bats
        │   │   │   ├── setup_file_halfway_error.bats
        │   │   │   ├── teardown_file.bats
        │   │   │   ├── teardown_file2.bats
        │   │   │   ├── teardown_file_after_failing_test.bats
        │   │   │   ├── teardown_file_after_long_test.bats
        │   │   │   ├── teardown_file_does_not_leak.bats
        │   │   │   ├── teardown_file_does_not_leak2.bats
        │   │   │   ├── teardown_file_even_if_all_tests_are_skipped.bats
        │   │   │   ├── teardown_file_failed.bats
        │   │   │   └── teardown_file_halfway_error.bats
        │   │   ├── junit-formatter/
        │   │   │   ├── duplicate/
        │   │   │   │   ├── first/
        │   │   │   │   │   └── file1.bats
        │   │   │   │   └── second/
        │   │   │   │       └── file1.bats
        │   │   │   ├── issue_360.bats
        │   │   │   ├── issue_531.bats
        │   │   │   ├── skipped.bats
        │   │   │   ├── suite/
        │   │   │   │   ├── file1.bats
        │   │   │   │   └── file2.bats
        │   │   │   └── xml-escape.bats
        │   │   ├── load/
        │   │   │   ├── ambiguous
        │   │   │   ├── ambiguous.bash
        │   │   │   ├── bats_load_library.bats
        │   │   │   ├── exit1.bash
        │   │   │   ├── failing_bats_load_library.bats
        │   │   │   ├── failing_load.bats
        │   │   │   ├── find_library_helper.bats
        │   │   │   ├── find_library_helper_err.bats
        │   │   │   ├── load.bats
        │   │   │   ├── return1.bash
        │   │   │   └── test_helper.bash
        │   │   ├── parallel/
        │   │   │   ├── must_not_parallelize_across_files/
        │   │   │   │   ├── file1.bats
        │   │   │   │   └── file2.bats
        │   │   │   ├── must_not_parallelize_within_file.bats
        │   │   │   ├── parallel-preserve-environment.bats
        │   │   │   ├── parallel.bats
        │   │   │   ├── parallel_factor.bats
        │   │   │   ├── setup_file/
        │   │   │   │   └── setup_file.bats
        │   │   │   └── suite/
        │   │   │       └── parallel1.bats
        │   │   ├── run/
        │   │   │   ├── failing.bats
        │   │   │   └── invalid.bats
        │   │   ├── suite/
        │   │   │   ├── empty/
        │   │   │   │   └── .gitkeep
        │   │   │   ├── filter/
        │   │   │   │   ├── a.bats
        │   │   │   │   ├── b.bats
        │   │   │   │   └── c.bats
        │   │   │   ├── multiple/
        │   │   │   │   ├── a.bats
        │   │   │   │   └── b.bats
        │   │   │   ├── override_BATS_FILE_EXTENSION/
        │   │   │   │   ├── subfolder/
        │   │   │   │   │   └── test.other_extension
        │   │   │   │   ├── test.bats
        │   │   │   │   └── test.test
        │   │   │   ├── recursive/
        │   │   │   │   ├── subsuite/
        │   │   │   │   │   └── test2.bats
        │   │   │   │   └── test.bats
        │   │   │   ├── single/
        │   │   │   │   └── test.bats
        │   │   │   ├── skip/
        │   │   │   │   ├── skip-in-setup-and-teardown.bats
        │   │   │   │   ├── skip-in-setup.bats
        │   │   │   │   ├── skip-in-teardown.bats
        │   │   │   │   ├── skip-in-test-and-teardown.bats
        │   │   │   │   └── skip-in-test.bats
        │   │   │   └── test_number/
        │   │   │       ├── file1.bats
        │   │   │       └── file2.bats
        │   │   └── trace/
        │   │       ├── failing_complex.bats
        │   │       └── failing_recursive.bats
        │   ├── install.bats
        │   ├── junit-formatter.bats
        │   ├── load.bats
        │   ├── parallel.bats
        │   ├── pretty-formatter.bats
        │   ├── root.bats
        │   ├── run.bats
        │   ├── suite.bats
        │   ├── test_helper.bash
        │   └── trace.bats
        └── uninstall.sh
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: vendor/bats-core/docs/source/conf.py
  function setup (line 68) | def setup(app):
Condensed preview — 380 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (774K chars).
[
  {
    "path": ".ci/docker-ci/alma/Dockerfile",
    "chars": 343,
    "preview": "FROM almalinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf insta"
  },
  {
    "path": ".ci/docker-ci/alpine/Dockerfile",
    "chars": 333,
    "preview": "FROM alpine:3.23.3\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\n# Don't install coreutils on Alp"
  },
  {
    "path": ".ci/docker-ci/arch/Dockerfile",
    "chars": 275,
    "preview": "FROM archlinux:base-20220529.0.58327\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN pacman -Sy"
  },
  {
    "path": ".ci/docker-ci/debian-gnupg1/Dockerfile",
    "chars": 513,
    "preview": "FROM debian:13.3-slim\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninter"
  },
  {
    "path": ".ci/docker-ci/debian-gnupg2/Dockerfile",
    "chars": 481,
    "preview": "FROM debian:13.3-slim\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninter"
  },
  {
    "path": ".ci/docker-ci/fedora/Dockerfile",
    "chars": 341,
    "preview": "FROM fedora:43\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install"
  },
  {
    "path": ".ci/docker-ci/rocky/Dockerfile",
    "chars": 344,
    "preview": "FROM rockylinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf inst"
  },
  {
    "path": ".ci/docker-ci/ubuntu/Dockerfile",
    "chars": 477,
    "preview": "FROM ubuntu:24.04\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND=\"noninteracti"
  },
  {
    "path": ".ci/github_release_script.sh",
    "chars": 1040,
    "preview": "#!/usr/bin/env sh\n\nset -e\n\n# Installing additional deps:\napk add --no-cache curl jq\n\n# https://gist.github.com/Jaskaranb"
  },
  {
    "path": ".ci/release-ci/alma/Dockerfile",
    "chars": 237,
    "preview": "FROM almalinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf insta"
  },
  {
    "path": ".ci/release-ci/alpine/Dockerfile",
    "chars": 175,
    "preview": "FROM alpine:3.23.3\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN apk add --no-cache --update "
  },
  {
    "path": ".ci/release-ci/debian/Dockerfile",
    "chars": 695,
    "preview": "FROM debian:13.3-slim\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninter"
  },
  {
    "path": ".ci/release-ci/fedora/Dockerfile",
    "chars": 371,
    "preview": "FROM fedora:43\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf install"
  },
  {
    "path": ".ci/release-ci/rocky/Dockerfile",
    "chars": 238,
    "preview": "FROM rockylinux:8\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nRUN dnf -y update \\\n  && dnf inst"
  },
  {
    "path": ".ci/release-ci/ubuntu/Dockerfile",
    "chars": 691,
    "preview": "FROM ubuntu:24.04\n\nLABEL maintainer=\"mail@sobolevn.me\"\nLABEL vendor=\"git-secret team\"\n\nENV DEBIAN_FRONTEND='noninteracti"
  },
  {
    "path": ".ci/releaser/alpine/Dockerfile",
    "chars": 978,
    "preview": "# Initially copied from\n# https://github.com/jordansissel/fpm/blob/master/Dockerfile\nFROM alpine:3.23.3\n\nSHELL [\"/bin/as"
  },
  {
    "path": ".editorconfig",
    "chars": 296,
    "preview": "# Check http://editorconfig.org for more information\n# This is the main config file for this project:\nroot = true\n\n[*]\nc"
  },
  {
    "path": ".gitattributes",
    "chars": 188,
    "preview": "# Excluding from GitHub languages:\nvendor/ linguist-vendored\n\n# Excluding from GitHub diff:\n*.1 linguist-generated\n*.7 l"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 134,
    "preview": "# These are supported funding model platforms\n\ngithub: wemake-services\nopen_collective: git-secret\ncustom: https://boost"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 1005,
    "preview": "<!-- Thanks for reporting an issue! Please make sure you click the link above to view the issue guidelines, then fill ou"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 1519,
    "preview": "<!-- Thanks for sending a pull request!\n\nHere's how it's done:\n0. If you are planning a large feature, please, discuss i"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 1685,
    "preview": "# GitHub-native dependabot setup, configuration:\n# https://docs.github.com/en/code-security/supply-chain-security/keepin"
  },
  {
    "path": ".github/workflows/build-man.yml",
    "chars": 507,
    "preview": "\nname: build-man\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - 'docs/**/*'\n      - '.github/workflows/bui"
  },
  {
    "path": ".github/workflows/github-pages.yml",
    "chars": 716,
    "preview": "name: github-pages\n\non:\n  push:\n    branches:\n      - master\n    paths:\n      - 'man/**/*'\n      - 'docs/**/*'\n      - '"
  },
  {
    "path": ".github/workflows/release-ci.yml",
    "chars": 2527,
    "preview": "name: release-ci\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 0 * * *'\n\n  # In case we change the some build scr"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1060,
    "preview": "name: release\n\non:\n  push:\n    tags:\n      - 'v*'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.head_ref || git"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1871,
    "preview": "name: test\n\non:\n  push:\n    branches:\n      - master\n    paths-ignore:\n      - 'docs/**'\n  pull_request:\n    paths-ignor"
  },
  {
    "path": ".gitignore",
    "chars": 2253,
    "preview": "#### joe made this: http://goel.io/joe\n\n#####=== Windows ===#####\n# Windows image file caches\nThumbs.db\nehthumbs.db\n\n# F"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 12895,
    "preview": "# Changelog\n\n## {{Next Version}}\n\n### Misc\n\n- NOTE: Arch instructions now say to install from source. Arch tests removed"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 10179,
    "preview": "# Contributing\n\nYour contributions are always welcome!\n\n\n## Getting started\n\n1. Create your own or pick an opened issue "
  },
  {
    "path": "LICENSE.md",
    "chars": 1071,
    "preview": "MIT License\n\nCopyright (c) 2016 Nikita Sobolev\n\nPermission is hereby granted, free of charge, to any person obtaining a "
  },
  {
    "path": "Makefile",
    "chars": 4586,
    "preview": "SHELL:=bash\nPREFIX?=\"/usr\"\nDESTDIR?=\n\n#\n# Building:\n#\n\n.PHONY: all\nall: build\n\n.PHONY: clean\nclean:\n\t@rm -f git-secret\n\n"
  },
  {
    "path": "README.md",
    "chars": 5170,
    "preview": "# git-secret\n\n\n[![test](https://github.com/sobolevn/git-secret/actions/workflows/test.yml/badge.svg?branch=master&event="
  },
  {
    "path": "RFC/RFC001.md",
    "chars": 6575,
    "preview": "# RFC 0001 - A stable and forwards compatible public key storage format\n\n**Feature Name:** Stable public key storage\n\n**"
  },
  {
    "path": "docs/Gemfile",
    "chars": 122,
    "preview": "source \"https://rubygems.org\"\n\ngroup :jekyll_plugins do\n  gem \"jekyll\", \">= 3.6.3\"\n  gem \"jekyll-seo-tag\", \"~> 2.8.0\"\nen"
  },
  {
    "path": "docs/_config.yml",
    "chars": 482,
    "preview": "# Site settings\ntitle: git-secret\nemail: mail@sobolevn.me\ndescription: Shell scripts to encrypt your private data inside"
  },
  {
    "path": "docs/_includes/favicons.html",
    "chars": 1497,
    "preview": "<link rel=\"apple-touch-icon\" sizes=\"57x57\"\n    href=\"/images/favicons/apple-icon-57x57.png\">\n<link rel=\"apple-touch-icon"
  },
  {
    "path": "docs/_includes/footer.html",
    "chars": 972,
    "preview": "<footer class=\"site-footer\">\n\n  <div class=\"wrapper\">\n\n    <h2 class=\"footer-heading\">{{ site.title }}</h2>\n\n    <div cl"
  },
  {
    "path": "docs/_includes/head.html",
    "chars": 820,
    "preview": "<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <meta name=\"viewport\" content="
  },
  {
    "path": "docs/_includes/header.html",
    "chars": 1654,
    "preview": "<header class=\"site-header\">\n\n  <div class=\"wrapper\">\n\n    <a class=\"site-title\" href=\"{{ site.baseurl }}/\">\n      {{ si"
  },
  {
    "path": "docs/_includes/icon-github.html",
    "chars": 188,
    "preview": "<a href=\"https://github.com/{{ include.username }}\">\n    <span class=\"icon icon--github\">{% include icon-github.svg %}</"
  },
  {
    "path": "docs/_includes/icon-twitter.html",
    "chars": 191,
    "preview": "<a href=\"https://twitter.com/{{ include.username }}\">\n    <span class=\"icon icon--twitter\">{% include icon-twitter.svg %"
  },
  {
    "path": "docs/_includes/why.md",
    "chars": 2291,
    "preview": "\n## Intro\n\nThere's a well known issue with deploying and configuring software on servers: \ngenerally you have to store y"
  },
  {
    "path": "docs/_layouts/default.html",
    "chars": 402,
    "preview": "<!DOCTYPE html>\n<html>\n\n  {% include head.html %}\n\n  <body>\n\n    {% include header.html %}\n\n    <div class=\"page-content"
  },
  {
    "path": "docs/_layouts/page.html",
    "chars": 209,
    "preview": "---\nlayout: default\n---\n<article class=\"post\">\n\n  <header class=\"post-header\">\n    <h1 class=\"post-title\">{{ page.title "
  },
  {
    "path": "docs/_layouts/post.html",
    "chars": 766,
    "preview": "---\nlayout: default\n---\n<article class=\"post\" itemscope itemtype=\"http://schema.org/BlogPosting\">\n\n  <header class=\"post"
  },
  {
    "path": "docs/_sass/_base.scss",
    "chars": 2917,
    "preview": "/**\n * Reset some basic elements\n */\nbody, h1, h2, h3, h4, h5, h6,\np, blockquote, pre, hr,\ndl, dd, ol, ul, figure {\n    "
  },
  {
    "path": "docs/_sass/_layout.scss",
    "chars": 4776,
    "preview": "/**\n * Site header\n */\n.site-header {\n    border-top: 5px solid $purple-color-dark;\n    border-bottom: 1px solid $purple"
  },
  {
    "path": "docs/_sass/_syntax-highlighting.scss",
    "chars": 3355,
    "preview": "/**\n * Syntax highlighting styles\n */\n.highlight {\n    background: #fff;\n    @extend %vertical-rhythm;\n\n    .highlighter"
  },
  {
    "path": "docs/build.sh",
    "chars": 1812,
    "preview": "#!/usr/bin/env bash\n\n# Should be called from the root folder, not inside `docs/` folder\n# See `make build-docs`\n\nset -e\n"
  },
  {
    "path": "docs/css/main.scss",
    "chars": 1209,
    "preview": "---\n# Only the main Sass file needs front matter (the dashes are enough)\n---\n@charset \"utf-8\";\n\n\n\n// Our variables\n$base"
  },
  {
    "path": "docs/feed.xml",
    "chars": 1291,
    "preview": "---\nlayout: null\n---\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">"
  },
  {
    "path": "docs/images/favicons/browserconfig.xml",
    "chars": 281,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig><msapplication><tile><square70x70logo src=\"/ms-icon-70x70.png\"/><s"
  },
  {
    "path": "docs/images/favicons/manifest.json",
    "chars": 720,
    "preview": "{\n \"name\": \"App\",\n \"icons\": [\n  {\n   \"src\": \"\\/android-icon-36x36.png\",\n   \"sizes\": \"36x36\",\n   \"type\": \"image\\/png\",\n  "
  },
  {
    "path": "docs/index.html",
    "chars": 875,
    "preview": "---\nlayout: default\n---\n\n<div class=\"home\">\n\n  <img src=\"{{ \"/images/git-secret-big.png\" | prepend: site.baseurl }}\"\n   "
  },
  {
    "path": "docs/installation.md",
    "chars": 5173,
    "preview": "---\nlayout: default\n---\n\n# Installation\n\n## Dependencies\n\n`git-secret` relies on two dependencies: `git` and `gpg`. Down"
  },
  {
    "path": "docs/plugins.md",
    "chars": 308,
    "preview": "---\nlayout: default\n---\n\n# External plugins\n\nHere's a list of external plugins for `git-secret` developed by other aweso"
  },
  {
    "path": "man/man1/git-secret-add.1",
    "chars": 1540,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-ADD\" \"1\" \"May 2022\" \"s"
  },
  {
    "path": "man/man1/git-secret-add.1.md",
    "chars": 1260,
    "preview": "git-secret-add - starts to track added files.\n=============================================\n\n## SYNOPSIS\n\n    git secret"
  },
  {
    "path": "man/man1/git-secret-cat.1",
    "chars": 1479,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-CAT\" \"1\" \"May 2022\" \"s"
  },
  {
    "path": "man/man1/git-secret-cat.1.md",
    "chars": 1217,
    "preview": "git-secret-cat - decrypts files passed on command line to stdout.\n=============================================\n\n## SYNO"
  },
  {
    "path": "man/man1/git-secret-changes.1",
    "chars": 1745,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-CHANGES\" \"1\" \"May 2022"
  },
  {
    "path": "man/man1/git-secret-changes.1.md",
    "chars": 1472,
    "preview": "git-secret-changes - view diff of the hidden files.\n===================================================\n\n## SYNOPSIS\n\n  "
  },
  {
    "path": "man/man1/git-secret-clean.1",
    "chars": 1484,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-CLEAN\" \"1\" \"May 2022\" "
  },
  {
    "path": "man/man1/git-secret-clean.1.md",
    "chars": 1205,
    "preview": "git-secret-clean - removes all the hidden files.\n================================================\n\n## SYNOPSIS\n\n    git "
  },
  {
    "path": "man/man1/git-secret-hide.1",
    "chars": 3693,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-HIDE\" \"1\" \"May 2022\" \""
  },
  {
    "path": "man/man1/git-secret-hide.1.md",
    "chars": 3195,
    "preview": "git-secret-hide - encrypts all added files with repo keyring.\n=========================================================="
  },
  {
    "path": "man/man1/git-secret-init.1",
    "chars": 1724,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-INIT\" \"1\" \"May 2022\" \""
  },
  {
    "path": "man/man1/git-secret-init.1.md",
    "chars": 1375,
    "preview": "git-secret-init - initializes git-secret repository.\n====================================================\n\n## SYNOPSIS\n\n"
  },
  {
    "path": "man/man1/git-secret-list.1",
    "chars": 1191,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-LIST\" \"1\" \"May 2022\" \""
  },
  {
    "path": "man/man1/git-secret-list.1.md",
    "chars": 928,
    "preview": "git-secret-list - prints all the added files.\n=============================================\n\n## SYNOPSIS\n\n    git secret"
  },
  {
    "path": "man/man1/git-secret-remove.1",
    "chars": 1447,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-REMOVE\" \"1\" \"May 2022\""
  },
  {
    "path": "man/man1/git-secret-remove.1.md",
    "chars": 1163,
    "preview": "git-secret-remove - removes files from index.\n=============================================\n\n## SYNOPSIS\n\n    git secret"
  },
  {
    "path": "man/man1/git-secret-removeperson.1",
    "chars": 1183,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-REMOVEPERSON\" \"1\" \"May"
  },
  {
    "path": "man/man1/git-secret-removeperson.1.md",
    "chars": 995,
    "preview": "git-secret-removeperson - removes user's public key from repo keyring.\n================================================="
  },
  {
    "path": "man/man1/git-secret-reveal.1",
    "chars": 2731,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-REVEAL\" \"1\" \"May 2022\""
  },
  {
    "path": "man/man1/git-secret-reveal.1.md",
    "chars": 2291,
    "preview": "git-secret-reveal - decrypts all added files.\n=============================================\n\n## SYNOPSIS\n\n    git secret"
  },
  {
    "path": "man/man1/git-secret-tell.1",
    "chars": 2500,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-TELL\" \"1\" \"May 2022\" \""
  },
  {
    "path": "man/man1/git-secret-tell.1.md",
    "chars": 2346,
    "preview": "git-secret-tell - adds person who can access private data.\n============================================================="
  },
  {
    "path": "man/man1/git-secret-usage.1",
    "chars": 875,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-USAGE\" \"1\" \"May 2022\" "
  },
  {
    "path": "man/man1/git-secret-usage.1.md",
    "chars": 651,
    "preview": "git-secret-usage - prints all the available commands.\n=====================================================\n\n## SYNOPSIS"
  },
  {
    "path": "man/man1/git-secret-whoknows.1",
    "chars": 965,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\\-WHOKNOWS\" \"1\" \"May 202"
  },
  {
    "path": "man/man1/git-secret-whoknows.1.md",
    "chars": 759,
    "preview": "git-secret-whoknows - print email for each key in the keyring.\n========================================================="
  },
  {
    "path": "man/man7/git-secret.7",
    "chars": 12334,
    "preview": ".\\\" generated with Ronn/v0.7.3\n.\\\" http://github.com/rtomayko/ronn/tree/0.7.3\n.\n.TH \"GIT\\-SECRET\" \"7\" \"June 2022\" \"sobol"
  },
  {
    "path": "man/man7/git-secret.7.md",
    "chars": 10941,
    "preview": "git-secret - bash tool to store private data inside a git repo.\n=============================================\n\n## Usage:"
  },
  {
    "path": "src/_utils/_git_secret_tools.sh",
    "chars": 21458,
    "preview": "#!/usr/bin/env bash\n\n# Folders:\n_SECRETS_DIR=${SECRETS_DIR:-\".gitsecret\"}\n# if SECRETS_DIR env var is set, use that inst"
  },
  {
    "path": "src/_utils/_git_secret_tools_freebsd.sh",
    "chars": 1325,
    "preview": "#!/usr/bin/env bash\n\n# support for freebsd. Mostly the same as MacOS.\n\n\n# shellcheck disable=SC1117\nfunction __replace_i"
  },
  {
    "path": "src/_utils/_git_secret_tools_linux.sh",
    "chars": 1534,
    "preview": "#!/usr/bin/env bash\n\n\n# shellcheck disable=SC1117\nfunction __replace_in_file_linux {\n  sed -i.bak \"s/^\\($1\\s*=\\s*\\).*\\$/"
  },
  {
    "path": "src/_utils/_git_secret_tools_osx.sh",
    "chars": 1350,
    "preview": "#!/usr/bin/env bash\n\n\n# shellcheck disable=SC1117\nfunction __replace_in_file_osx {\n  sed -i.bak \"s/^\\($1[[:space:]]*=[[:"
  },
  {
    "path": "src/commands/git_secret_add.sh",
    "chars": 2212,
    "preview": "#!/usr/bin/env bash\n\n\nfunction add {\n  OPTIND=1\n\n  while getopts \"ihv\" opt; do\n    case \"$opt\" in\n      i) ;;    # this "
  },
  {
    "path": "src/commands/git_secret_cat.sh",
    "chars": 752,
    "preview": "#!/usr/bin/env bash\n\n\nfunction cat {\n  local homedir=''\n  local passphrase=''\n\n  OPTIND=1\n\n  while getopts 'hd:p:' opt; "
  },
  {
    "path": "src/commands/git_secret_changes.sh",
    "chars": 1933,
    "preview": "#!/usr/bin/env bash\n\nfunction changes {\n  local passphrase=\"\"\n\n  OPTIND=1\n\n  while getopts 'hd:p:' opt; do\n    case \"$op"
  },
  {
    "path": "src/commands/git_secret_clean.sh",
    "chars": 440,
    "preview": "#!/usr/bin/env bash\n\n\nfunction clean {\n  OPTIND=1\n\n  # shellcheck disable=SC2034\n  while getopts 'vh' opt; do\n    case \""
  },
  {
    "path": "src/commands/git_secret_hide.sh",
    "chars": 5959,
    "preview": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2016\nAWK_FSDB_UPDATE_HASH='\nBEGIN { FS=\":\"; OFS=\":\"; }\n{\n  if ( key == $1 )\n"
  },
  {
    "path": "src/commands/git_secret_init.sh",
    "chars": 1722,
    "preview": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2016\nAWK_ADD_TO_GITIGNORE='\nBEGIN {\n  cnt=0\n}\n\nfunction check_print_line(lin"
  },
  {
    "path": "src/commands/git_secret_list.sh",
    "chars": 544,
    "preview": "#!/usr/bin/env bash\n\n\nfunction list {\n  OPTIND=1\n\n  while getopts 'h' opt; do\n    case \"$opt\" in\n      h) _show_manual_f"
  },
  {
    "path": "src/commands/git_secret_remove.sh",
    "chars": 1420,
    "preview": "#!/usr/bin/env bash\n\n\nfunction remove {\n  local clean=0\n\n  OPTIND=1\n\n  while getopts 'ch' opt; do\n    case \"$opt\" in\n   "
  },
  {
    "path": "src/commands/git_secret_removeperson.sh",
    "chars": 1589,
    "preview": "#!/usr/bin/env bash\n\n\nfunction removeperson {\n  OPTIND=1\n\n  while getopts 'h' opt; do\n    case \"$opt\" in\n      h) _show_"
  },
  {
    "path": "src/commands/git_secret_reveal.sh",
    "chars": 2091,
    "preview": "#!/usr/bin/env bash\n\n\nfunction reveal {\n  local homedir=''\n  local passphrase=''\n  local force=0             # this mean"
  },
  {
    "path": "src/commands/git_secret_tell.sh",
    "chars": 3850,
    "preview": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2016\nAWK_GPG_KEY_CNT='\nBEGIN { cnt=0; OFS=\":\"; FS=\":\"; }\nflag=0; $1 == \"pub\""
  },
  {
    "path": "src/commands/git_secret_usage.sh",
    "chars": 1505,
    "preview": "#!/usr/bin/env bash\n\n\nfunction usage {\n  OPTIND=1\n\n  while getopts \"h?\" opt; do\n    case \"$opt\" in\n      h) _show_manual"
  },
  {
    "path": "src/commands/git_secret_whoknows.sh",
    "chars": 992,
    "preview": "#!/usr/bin/env bash\n\n\nfunction whoknows {\n  OPTIND=1\n\n  local long_display=0\n  while getopts \"hl?\" opt; do\n    case \"$op"
  },
  {
    "path": "src/main.sh",
    "chars": 1768,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nfunction _check_setup {\n  # Checking git and secret-plugin setup:\n  local is_tree\n  is_tree"
  },
  {
    "path": "src/version.sh",
    "chars": 82,
    "preview": "#!/usr/bin/env bash\n\n# shellcheck disable=SC2034\nGITSECRET_VERSION='0.5.1-alpha1'\n"
  },
  {
    "path": "tests/_test_base.bash",
    "chars": 10912,
    "preview": "#!/usr/bin/env bash\n\n# This file is following a name convention defined in:\n# https://github.com/bats-core/bats-core\n\n# "
  },
  {
    "path": "tests/fixtures/gpg/README.md",
    "chars": 1494,
    "preview": "== public/private key pairs for test keys\n\n* git-secret test keys are named user1@gitsecret.io through \n  user5@gitsecre"
  },
  {
    "path": "tests/fixtures/gpg/attacker1@gitsecret.io/private.key",
    "chars": 3569,
    "preview": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v1\n\nlQO+BFaigVQBCADC5dJ0xweZ+6L0owo2wpKSbQFGQoRJxYVcc1dWe3zNZ5yBrJD"
  },
  {
    "path": "tests/fixtures/gpg/attacker1@gitsecret.io/public.key",
    "chars": 1702,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFaigVQBCADC5dJ0xweZ+6L0owo2wpKSbQFGQoRJxYVcc1dWe3zNZ5yBrJDV"
  },
  {
    "path": "tests/fixtures/gpg/user1@gitsecret.io/private.key",
    "chars": 3561,
    "preview": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v1\n\nlQO+BFaigO0BCACwtBp5eg1d68f9WhmYew/4eU5zjaJsNj1DHsHokxsUt9QpIdV"
  },
  {
    "path": "tests/fixtures/gpg/user1@gitsecret.io/public.key",
    "chars": 1694,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFaigO0BCACwtBp5eg1d68f9WhmYew/4eU5zjaJsNj1DHsHokxsUt9QpIdVq"
  },
  {
    "path": "tests/fixtures/gpg/user2@gitsecret.io/private.key",
    "chars": 3561,
    "preview": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v1\n\nlQO9BFaigRUBCACgb+7xhV1nJZim3noxozslfrWXPYEVQt7Is8QjATaKg6ULqIm"
  },
  {
    "path": "tests/fixtures/gpg/user2@gitsecret.io/public.key",
    "chars": 1694,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQENBFaigRUBCACgb+7xhV1nJZim3noxozslfrWXPYEVQt7Is8QjATaKg6ULqImi"
  },
  {
    "path": "tests/fixtures/gpg/user3@gitsecret.io/private.key",
    "chars": 3651,
    "preview": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nlQPGBFtLVc0BCACwGHyefi/z8xeH6KpLN2k9+PlHAPpwJa"
  },
  {
    "path": "tests/fixtures/gpg/user3@gitsecret.io/public.key",
    "chars": 1760,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nmQENBFtLVc0BCACwGHyefi/z8xeH6KpLN2k9+PlHAPpwJaW"
  },
  {
    "path": "tests/fixtures/gpg/user4@gitsecret.io/private.key",
    "chars": 3586,
    "preview": "-----BEGIN PGP PRIVATE KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nlQO+BFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcA"
  },
  {
    "path": "tests/fixtures/gpg/user4@gitsecret.io/public.key",
    "chars": 1719,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v2.0.22 (GNU/Linux)\n\nmQENBFumzaQBCADp6MO1IRBIbdJoABK3EUWxBjZKE/jAcAY"
  },
  {
    "path": "tests/fixtures/gpg/user5@gitsecret.io/private.key",
    "chars": 3620,
    "preview": "-----BEGIN PGP PRIVATE KEY BLOCK-----\n\nlQPGBF1yX48BCAC7TVKvW81RjJKcGI21cI1iUEPkpWCqXwUjt9UsJ8g+2BW45gmX\n9tLKPp5ax6hJoLQp"
  },
  {
    "path": "tests/fixtures/gpg/user5@gitsecret.io/public.key",
    "chars": 1733,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQENBF1yX48BCAC7TVKvW81RjJKcGI21cI1iUEPkpWCqXwUjt9UsJ8g+2BW45gmX\n9tLKPp5ax6hJoLQpc"
  },
  {
    "path": "tests/test_add.bats",
    "chars": 6452,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n"
  },
  {
    "path": "tests/test_cat.bats",
    "chars": 2151,
    "preview": "#!/usr/bin/env bats\n# shellcheck disable=SC2030,SC2031\n# above is to avoid shellcheck info warnings that we don't unders"
  },
  {
    "path": "tests/test_changes.bats",
    "chars": 5643,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE_TO_HIDE=\"$TEST_SECOND_FILENAME\"\n"
  },
  {
    "path": "tests/test_clean.bats",
    "chars": 2043,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFIRST_FILE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE=\"$TEST_SECOND_FILENAME\"\n\n\nfunction"
  },
  {
    "path": "tests/test_expiration.bats",
    "chars": 1921,
    "preview": "#!/usr/bin/env bats\n\nexport TZ=\"GMT\"\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_EXPIRED_USER\"\n\n  s"
  },
  {
    "path": "tests/test_hide.bats",
    "chars": 8486,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\n\nfunc"
  },
  {
    "path": "tests/test_hide_continue.bats",
    "chars": 1257,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_TO_HIDE2=\"$TEST_SECOND_FILENAME\"\nFILE_C"
  },
  {
    "path": "tests/test_init.bats",
    "chars": 2477,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  set_state_initial\n  set_state_git\n}\n\n\nfunction teardown {\n  un"
  },
  {
    "path": "tests/test_list.bats",
    "chars": 1275,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"file_to_hide\"\nFILE_CONTENTS=\"hidden content юникод\"\n\n\nfunction setup"
  },
  {
    "path": "tests/test_main.bats",
    "chars": 710,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  set_state_initial\n  set_state_git\n}\n\n\nfunction teardown {\n  un"
  },
  {
    "path": "tests/test_make_install.bats",
    "chars": 393,
    "preview": "#!/usr/bin/env bats\n\n: \"${TMPDIR:=/tmp}\"\n\nINSTALL_BASE=\"${TMPDIR}/git-secret-test-install\"\n\n\n@test \"install git-secret t"
  },
  {
    "path": "tests/test_noname.bats",
    "chars": 1393,
    "preview": "#!/usr/bin/env bats\n\n# These tests using TEST_NONAME_USER, which has a email but no username.\n# This was originally base"
  },
  {
    "path": "tests/test_remove.bats",
    "chars": 2671,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFIRST_FILE=\"$TEST_DEFAULT_FILENAME\"\nSECOND_FILE=\"$TEST_SECOND_FILENAME\"\n\n\nfunction"
  },
  {
    "path": "tests/test_removeperson.bats",
    "chars": 2804,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n"
  },
  {
    "path": "tests/test_reveal.bats",
    "chars": 8031,
    "preview": "#!/usr/bin/env bats\n# shellcheck disable=SC2155\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"h"
  },
  {
    "path": "tests/test_reveal_filename.bats",
    "chars": 1072,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\nFILE_TO_HIDE=\"$TEST_DEFAULT_FILENAME\"\nFILE_CONTENTS=\"hidden content юникод\"\n\nFINGE"
  },
  {
    "path": "tests/test_tell.bats",
    "chars": 7331,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n\n  set_state_initial\n"
  },
  {
    "path": "tests/test_usage.bats",
    "chars": 884,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  set_state_initial\n  set_state_git\n}\n\n\nfunction teardown {\n  un"
  },
  {
    "path": "tests/test_whoknows.bats",
    "chars": 2252,
    "preview": "#!/usr/bin/env bats\n\nload _test_base\n\n\nfunction setup {\n  install_fixture_key \"$TEST_DEFAULT_USER\"\n  install_fixture_key"
  },
  {
    "path": "utils/apk/build.sh",
    "chars": 1136,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n# We"
  },
  {
    "path": "utils/apk/deploy.sh",
    "chars": 1137,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nif [[ \"$SECRETS_DEPLOY_DRY_RUN\" == 1 ]]; then\n  echo 'dry-run finished'\n  exit 0\nfi\n\n# shel"
  },
  {
    "path": "utils/apk/install.sh",
    "chars": 343,
    "preview": "sh -c \"echo 'https://gitsecret.jfrog.io/artifactory/git-secret-apk/latest-stable/main'\" >> /etc/apk/repositories\nwget -O"
  },
  {
    "path": "utils/apk/meta.sh",
    "chars": 189,
    "preview": "# Full list is here:\n# http://dl-cdn.alpinelinux.org/alpine/v3.13/main/\n# shellcheck disable=SC2034\nreadonly ALPINE_ARCH"
  },
  {
    "path": "utils/apk/nfpm.yml",
    "chars": 894,
    "preview": "# Name. (required)\nname: git-secret\n\n# Architecture. (required)\narch: $ALPINE_ARCHITECTURE\n\n# Platform.\n# Defaults to `l"
  },
  {
    "path": "utils/build-utils.sh",
    "chars": 2419,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/src/version.sh\"\n\n# Initial"
  },
  {
    "path": "utils/deb/build.sh",
    "chars": 241,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n\npre"
  },
  {
    "path": "utils/deb/deploy.sh",
    "chars": 836,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nif [[ \"$SECRETS_DEPLOY_DRY_RUN\" == 1 ]]; then\n  echo 'dry-run finished'\n  exit 0\nfi\n\n# shel"
  },
  {
    "path": "utils/deb/install.sh",
    "chars": 318,
    "preview": "sudo sh -c \"echo 'deb https://gitsecret.jfrog.io/artifactory/git-secret-deb git-secret main' >> /etc/apt/sources.list\"\nw"
  },
  {
    "path": "utils/install.sh",
    "chars": 1068,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n\n# Credit goes to:\n# https://github.com/sstephenson/bats/blob/master/install.sh\nfunction re"
  },
  {
    "path": "utils/rpm/build.sh",
    "chars": 298,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n# shellcheck disable=SC1090,SC1091\nsource \"$SECRETS_PROJECT_ROOT/utils/build-utils.sh\"\n\n# C"
  },
  {
    "path": "utils/rpm/deploy.sh",
    "chars": 772,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nif [[ \"$SECRETS_DEPLOY_DRY_RUN\" == 1 ]]; then\n  echo 'dry-run finished'\n  exit 0\nfi\n\n# shel"
  },
  {
    "path": "utils/rpm/git-secret.repo",
    "chars": 301,
    "preview": "[git-secret-rpm]\nname=git-secret-rpm\nbaseurl=https://gitsecret.jfrog.io/artifactory/git-secret-rpm\nenabled=1\ngpgcheck=0\n"
  },
  {
    "path": "utils/rpm/install.sh",
    "chars": 313,
    "preview": "wget https://raw.githubusercontent.com/sobolevn/git-secret/master/utils/rpm/git-secret.repo -O git-secret-rpm.repo\n# Ins"
  },
  {
    "path": "utils/tests.sh",
    "chars": 754,
    "preview": "#!/usr/bin/env bash\n\n# `SECRETS_PROJECT_ROOT` must be set before running the script.\n\nset -e\n\nTEST_DIR=\"/tmp/git-secret-"
  },
  {
    "path": "utils/uninstall.sh",
    "chars": 298,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n\nreadonly PREFIX=\"$1\"\nif [ -z \"$PREFIX\" ]; then\n  echo \"usage: $0 <prefix>\" >&2\n  exit 1\nfi"
  },
  {
    "path": "vendor/README.md",
    "chars": 380,
    "preview": "README for git-secret/vendor directory\n\nWe import bats-core here for\nhttps://github.com/sobolevn/git-secret/issues/377,\n"
  },
  {
    "path": "vendor/bats-core/.devcontainer/Dockerfile",
    "chars": 519,
    "preview": "ARG bashver=latest\n\nFROM bash:${bashver}\n\n# Install parallel and accept the citation notice (we aren't using this in a\n#"
  },
  {
    "path": "vendor/bats-core/.devcontainer/devcontainer.json",
    "chars": 126,
    "preview": "{\n    \"name\": \"Bats core development environment\",\n    \"dockerFile\": \"Dockerfile\",\n    \"build\": {\"args\": {\"bashver\": \"4."
  },
  {
    "path": "vendor/bats-core/.editorconfig",
    "chars": 687,
    "preview": "root = true\n\n[*]\nend_of_line = lf\nindent_style = space\nindent_size = 2\ninsert_final_newline = true\nmax_line_length = 80\n"
  },
  {
    "path": "vendor/bats-core/.gitattributes",
    "chars": 41,
    "preview": "* text=auto\n*.sh eol=lf\nlibexec/* eol=lf\n"
  },
  {
    "path": "vendor/bats-core/.github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 636,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: 'Type: Bug'\nassignees: ''\n\n---\n\n**Descr"
  },
  {
    "path": "vendor/bats-core/.github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 597,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: 'Type: Enhancement'\nassignees: ''\n\n-"
  },
  {
    "path": "vendor/bats-core/.github/workflows/check_pr_label.sh",
    "chars": 240,
    "preview": "#!/usr/bin/bash\n\nget_pr_json() {\n    curl -s -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/b"
  },
  {
    "path": "vendor/bats-core/.github/workflows/release.yml",
    "chars": 789,
    "preview": "name: Release\n\non:\n  release: { types: [published] }\n  workflow_dispatch:\n\njobs:\n  npmjs:\n    runs-on: ubuntu-latest\n   "
  },
  {
    "path": "vendor/bats-core/.github/workflows/release_dockerhub.yml",
    "chars": 1290,
    "preview": "name: Release to docker hub\n\non:\n  release: { types: [published] }\n  workflow_dispatch:\n    inputs:\n        version:\n   "
  },
  {
    "path": "vendor/bats-core/.github/workflows/tests.yml",
    "chars": 5449,
    "preview": "name: Tests\n\n# Controls when the action will run. \non: [push, pull_request, workflow_dispatch]\n\njobs:\n  changelog:\n    r"
  },
  {
    "path": "vendor/bats-core/.gitignore",
    "chars": 131,
    "preview": "/docker-compose.override.yml\n/docs/build\n\n# npm\n/bats-*.tgz\n# we don't have any deps; un-ignore if that changes\n/package"
  },
  {
    "path": "vendor/bats-core/.readthedocs.yml",
    "chars": 140,
    "preview": "version: 2\n\nsphinx:\n  configuration: docs/source/conf.py\n\npython:\n  version: 3.7\n  install:\n    - requirements: docs/sou"
  },
  {
    "path": "vendor/bats-core/AUTHORS",
    "chars": 219,
    "preview": "Andrew Martin (https://control-plane.io/)\nBianca Tamayo <hi@biancatamayo.me> (https://biancatamayo.me/)\nJason Karns <jas"
  },
  {
    "path": "vendor/bats-core/Dockerfile",
    "chars": 648,
    "preview": "ARG bashver=latest\n\nFROM bash:${bashver}\nARG TINI_VERSION=v0.19.0\nARG TARGETPLATFORM\n\nCOPY ./docker /tmp/docker\n# defaul"
  },
  {
    "path": "vendor/bats-core/LICENSE.md",
    "chars": 2535,
    "preview": "Copyright (c) 2017 bats-core contributors\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy "
  },
  {
    "path": "vendor/bats-core/README.md",
    "chars": 4351,
    "preview": "# Bats-core: Bash Automated Testing System (2018)\n\n[![Latest release](https://img.shields.io/github/release/bats-core/ba"
  },
  {
    "path": "vendor/bats-core/bin/bats",
    "chars": 1675,
    "preview": "#!/usr/bin/env bash\n\nset -euo pipefail\n\nif command -v greadlink >/dev/null; then\n  bats_readlinkf() {\n    greadlink -f \""
  },
  {
    "path": "vendor/bats-core/contrib/release.sh",
    "chars": 3771,
    "preview": "#!/usr/bin/env bash\n#\n# bats-core git releaser\n#\n## Usage: %SCRIPT_NAME% [options]\n##\n## Options:\n##   --major          "
  },
  {
    "path": "vendor/bats-core/contrib/rpm/bats.spec",
    "chars": 1575,
    "preview": "%global provider        github.com\n%global project         bats-core\n%global repo            bats-core\n\nName:           "
  },
  {
    "path": "vendor/bats-core/contrib/semver",
    "chars": 7973,
    "preview": "#!/usr/bin/env bash\n\n# v3.0.0\n# https://github.com/fsaintjacques/semver-tool\n\nset -o errexit -o nounset -o pipefail\n\nNAT"
  },
  {
    "path": "vendor/bats-core/docker/install_tini.sh",
    "chars": 656,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\ncase ${1#linux/} in\n    386) \n        TINI_PLATFORM=i386 \n        ;;\n    arm/v7)\n        TI"
  },
  {
    "path": "vendor/bats-core/docker/tini.pubkey.gpg",
    "chars": 6762,
    "preview": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBFANDtsBEACpb69Ul0Ko7D4XxRIvPGnDMuGdocb8PxR+EGbnHe0uS2tCbsfj\nTOoWWUrjufrWYxGlK"
  },
  {
    "path": "vendor/bats-core/docker-compose.override.dist",
    "chars": 147,
    "preview": "# Copy this file to docker-compose.override.yml\nversion: '3.6'\nservices:\n    bats:\n        entrypoint:\n            - \"ba"
  },
  {
    "path": "vendor/bats-core/docker-compose.yml",
    "chars": 244,
    "preview": "version: '3.6'\nservices:\n    bats:\n        build:\n            context: \".\"\n            dockerfile: \"Dockerfile\"\n        "
  },
  {
    "path": "vendor/bats-core/docs/.markdownlint.json",
    "chars": 41,
    "preview": "{\n  \"MD024\": { \"siblings_only\": true }\n}\n"
  },
  {
    "path": "vendor/bats-core/docs/CHANGELOG.md",
    "chars": 13149,
    "preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
  },
  {
    "path": "vendor/bats-core/docs/CODEOWNERS",
    "chars": 211,
    "preview": "# This enables automatic code review requests per:\n# - https://help.github.com/articles/about-codeowners/\n# - https://he"
  },
  {
    "path": "vendor/bats-core/docs/CODE_OF_CONDUCT.md",
    "chars": 3643,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "vendor/bats-core/docs/CONTRIBUTING.md",
    "chars": 17077,
    "preview": "# Contributing Guidelines\n\n## Welcome!\n\nThank you for considering contributing to the development of this project's \ndev"
  },
  {
    "path": "vendor/bats-core/docs/Makefile",
    "chars": 638,
    "preview": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line, and also\n# from the "
  },
  {
    "path": "vendor/bats-core/docs/PULL_REQUEST_TEMPLATE.md",
    "chars": 317,
    "preview": "- [ ] I have reviewed the [Contributor Guidelines][contributor].\n- [ ] I have reviewed the [Code of Conduct][coc] and ag"
  },
  {
    "path": "vendor/bats-core/docs/examples/README.md",
    "chars": 175,
    "preview": "# Examples\n\nThis directory contains example .bats files.\nSee the [bats-core wiki][examples] for more details.\n\n[examples"
  },
  {
    "path": "vendor/bats-core/docs/examples/package-tarball",
    "chars": 604,
    "preview": "#!/usr/bin/env bash\n\n# \"unofficial\" bash strict mode\n# See: http://redsymbol.net/articles/unofficial-bash-strict-mode\nse"
  },
  {
    "path": "vendor/bats-core/docs/examples/package-tarball.bats",
    "chars": 992,
    "preview": "#!/usr/bin/env bats\n\nsetup() {\n  export dst_tarball=\"${BATS_TMPDIR}/dst.tar.gz\"\n  export src_dir=\"${BATS_TMPDIR}/src_dir"
  },
  {
    "path": "vendor/bats-core/docs/make.bat",
    "chars": 764,
    "preview": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-bu"
  },
  {
    "path": "vendor/bats-core/docs/releasing.md",
    "chars": 3963,
    "preview": "# Releasing a new Bats version\n\nThese notes reflect the current process. There's a lot more we could do, in\nterms of aut"
  },
  {
    "path": "vendor/bats-core/docs/source/_static/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "vendor/bats-core/docs/source/_templates/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "vendor/bats-core/docs/source/conf.py",
    "chars": 2418,
    "preview": "# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common op"
  },
  {
    "path": "vendor/bats-core/docs/source/docker-usage.md",
    "chars": 2363,
    "preview": "# Docker Usage Guide\n\n- [Docker Usage Guide](#docker-usage-guide)\n  * [Basic Usage](#basic-usage)\n  * [Docker Gotchas](#"
  },
  {
    "path": "vendor/bats-core/docs/source/faq.rst",
    "chars": 5999,
    "preview": "FAQ\n===\n\nHow do I set the working directory?\n-----------------------------------\n\nThe working directory is simply the di"
  },
  {
    "path": "vendor/bats-core/docs/source/gotchas.rst",
    "chars": 5857,
    "preview": "Gotchas\n=======\n\nMy test fails although I return true?\n-------------------------------------\n\nUsing `return 1` to signif"
  },
  {
    "path": "vendor/bats-core/docs/source/index.rst",
    "chars": 343,
    "preview": "Welcome to bats-core's documentation!\n=====================================\n\nVersions before v1.2.1 are documented over "
  },
  {
    "path": "vendor/bats-core/docs/source/installation.rst",
    "chars": 3826,
    "preview": "\nInstallation\n============\n\nSupported Bash versions\n^^^^^^^^^^^^^^^^^^^^^^^\n\nThe following is a list of Bash versions th"
  },
  {
    "path": "vendor/bats-core/docs/source/requirements.txt",
    "chars": 40,
    "preview": "sphinxcontrib-programoutput\nrecommonmark"
  },
  {
    "path": "vendor/bats-core/docs/source/tutorial.rst",
    "chars": 21498,
    "preview": "Tutorial\n========\n\nThis tutorial is intended for beginners with bats and possibly bash.\nMake sure to also read the list "
  }
]

// ... and 180 more files (download for full content)

About this extraction

This page contains the full source code of the sobolevn/git-secret GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 380 files (689.9 KB), approximately 227.7k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!