# Git<no value>
// <!-- Required for asciidoctor -->
:toc:
// Set toclevels to be at least your hugo [markup.tableOfContents.endLevel] config key
:toclevels: 4

== Description

The `git` scm plugin clones a git repository from any URL and pushes changes back to it. It knows nothing about the hosting platform, which makes it the fallback for servers Updatecli has no dedicated plugin for. It is referenced by a resource through its `scmid`, as described on the link:/docs/core/scm/["SCM" page].

Its behavior depends on the stage referencing it:

**source** and **condition**::
The repository is cloned and the resource works on the files from the branch defined by `branch`. Nothing is pushed.

**target**::
The changes are committed and pushed. *By default they go straight to `branch`*, because `workingBranch` defaults to `false` on this plugin. See <<_working_branch>> to commit to a dedicated branch instead.

[NOTE]
====
Prefer the dedicated plugin when one exists - link:/docs/plugins/scm/github/[GitHub], link:/docs/plugins/scm/gitlab/[GitLab], link:/docs/plugins/scm/gitea/[Gitea], link:/docs/plugins/scm/bitbucket/[Bitbucket], link:/docs/plugins/scm/stash/[Stash], link:/docs/plugins/scm/azuredevops/[Azure DevOps]. They default to a working branch and can be paired with an action that opens a pull request. The `git` plugin can only push; no pull request will ever be opened from it.
====

== Parameters

{{< resourceparameters "scms" "git" >}}

`url` is the only mandatory parameter. It accepts both protocols:

[source,yaml]
----
url: "https://github.com/updatecli/updatecli.git"   # HTTP(S)
url: "git@github.com:updatecli/updatecli.git"       # SSH
----

NOTE: The table above is generated from the Updatecli JSON schema, refreshed by a bot after each release. A recently added parameter (currently `singleBranch`, which restricts clone and fetch to the configured branch) may work in the binary before it shows up here.

=== Authentication

How Updatecli authenticates follows from the URL scheme.

HTTP(S)::
`username` and `password` are sent as HTTP basic credentials. On most platforms the "password" is a personal access token rather than an account password, and the username can be any non-empty value. Keep them out of the manifest itself:
+
[source,yaml]
----
username: '{{ requiredEnv "GIT_USERNAME" }}'
password: '{{ requiredEnv "GIT_TOKEN" }}'
----

SSH::
`username` and `password` are ignored. Updatecli relies on your local ssh-agent, so the key must already be loaded (`ssh-add -l` should list it) and the agent reachable through `SSH_AUTH_SOCK`. There is no parameter to point at a private key file.

Anonymous access works for public repositories over HTTPS when both fields are left empty, which is enough for a source or a condition.

[[_working_branch]]
=== Working branch

Unlike the platform-specific plugins, `git` commits directly to `branch` unless you opt in. Setting `workingBranch: true` makes Updatecli create a dedicated branch instead:

[source,text]
----
<workingBranchPrefix><workingBranchSeparator><branch><workingBranchSeparator><pipelineID>
----

With the defaults (`updatecli` and `_`), a pipeline based on `main` produces `updatecli_main_<pipelineID>`, where `pipelineID` is a hash derived from the manifest, so the same pipeline reuses the same branch instead of piling up new ones. Characters git refuses in a ref are stripped, and the name is truncated to 255 characters. Setting `workingBranchPrefix: ""` gives `<branch>_<pipelineID>`.

`branch` itself defaults to `main`.

=== Force push

`force` runs `git push --force`, and also makes Updatecli recreate working branches that diverged from their base branch. It defaults to `false` here.

Because force-pushing straight onto a shared branch is destructive, and because some targets (the `shell` one, for instance) stage every change in the working tree, combining `force: true` with an unset `workingBranch` is refused:

[source,text]
----
Better safe than sorry.

The scm force option set to true means that Updatecli is going to run "git push --force"
----

Set `workingBranch` explicitly (to `true` to force-push a dedicated branch, or to `false` to confirm you really mean the shared one).

=== Commit message

Updatecli generates link:https://www.conventionalcommits.org/[conventional commits]. The `commitMessage` parameters (`type`, `scope`, `body`, `footers`, `hideCredit`, `squash`) shape the result.

The commit title always comes from the target's `name`, or from its description when `name` is unset. It is capped at 72 characters minus the room taken by `type` and `scope`; the overflow is moved into the body. With the default type `chore`:

[source,text]
----
Author: updatecli-bot <updatecli-bot@updatecli.io>
Date:   Tue May 4 15:41:44 2021 +0200

    chore: Update key "dependencies[0].version" from file "charts/jenkins/r...

    ... equirements.yaml"

    Made with ❤️️  by updatecli
----

Setting `body` replaces the generated body entirely, including that overflow. `hideCredit: true` drops the credit line. `squash: true` collapses the commits added on the working branch into one (set `body` when you use it, since the individual messages are lost).

[WARNING]
====
`commitMessage.title` is deprecated and ignored. Rename the target instead; Updatecli logs a warning when the field is present.
====

NOTE: `commitMessage` applies to every target linked to the same scm.

=== Commit signing

`gpg.signingkey` takes an *armored private* GPG key (not the public half) and `gpg.passphrase` its passphrase. Both are secrets and belong in an environment variable or a SOPS file:

[source,yaml]
----
gpg:
  signingkey: '{{ requiredEnv "GPG_SIGNING_KEY" }}'
  passphrase: '{{ requiredEnv "GPG_PASSPHRASE" }}'
----

=== Clone behavior

Left unset, `directory` is derived from the URL under your system temporary directory - `/tmp/updatecli/github_com_updatecli_updatecli_git` on Linux for `https://github.com/updatecli/updatecli.git`, with the protocol dropped and separators replaced. Overriding it is rarely useful, as Updatecli may clean that directory up after a run.

`submodules`:: Defaults to `true`; set it to `false` to skip submodule checkout.
`depth`:: Number of commits to fetch. Unset means a full clone. A shallow clone leaves Updatecli with an incomplete history, which can break pushes; `force: true` is often needed alongside.
`singleBranch`:: Defaults to `false`, meaning every branch, tag, and ref is fetched. Setting it to `true` fetches only `branch`, which is much faster on repositories with many refs, at the cost of Updatecli sometimes failing to notice an already published working branch.

=== Commit identity

`user` and `email` name the commit author, defaulting to `updatecli-bot` and `updatecli-bot@updatecli.io`.

== Example

The manifest below uses three separate scms: one to read a file, one to test a condition, and one over SSH to push a change on a working branch.

[source,yaml]
----
# updatecli.yaml
{{< include "assets/code_example/docs/plugins/scm/git/updatecli.d/default.yaml" >}}
----
