Question: I would like to tag resources created by Terraform with GIT revision hash, ref name and also record if the checkout is clean or dirty. I have found a [git provider](https://github.com/innovationnorway/terraform-provider-git) that has some of the information, but not all. I would like to inform operators looking at the actual resources what was deployed last by whom.

Answer: 
Terraform has no built-in integration with version control systems, but there are three main ways to get external information like that into Terraform:

1. You can pass data into your configuration at execution time using [input variables](https://www.terraform.io/language/values/variables) declared in your root module.

In order to use this approach for "systematic" data collection which must always be done consistently, you'd typically need to wrap Terraform in a wrapper script or remote automation to ensure that the data is collected and passed in consistently every time.
2. You can use a [data source](https://www.terraform.io/language/data-sources) offered by a provider, in which case Terraform will read from it during the planning step and expose the data for use elsewhere your module.

[The Git provider you linked to](https://github.com/innovationnorway/terraform-provider-git) would be an example of this strategy. The `git_repository` mentioned in its usage (at the time I'm writing this, at least) is an example of a data source.

If that provider doesn't offer all of the data you need then you may be able to contribute additional functionality to it, since it is open source, or you could [write your own provider](https://www.terraform.io/plugin) that more directly meets your needs.
3. As a variant of the previous option, [the `hashicorp/external` provider](https://registry.terraform.io/providers/hashicorp/external/latest/docs) includes a special generic data source just called [`external`](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) which obtains data by running a particular external program, as long as the program generates output in a prescribed format that the provider understands.

This can be a convenient escape hatch if there isn't already a provider that offers a more specialized data source, but it does introduce a dependency on external software outside of Terraform's direct scope, which may make it more complicated to use your Terraform configuration across different operating systems that may have different software or versions of software installed.

These are all general mechanisms that can be appropriate for *any* data which originates outside of a Terraform configuration. Since Terraform is not itself aware of your version control system, information about the state of that system counts as coming from outside.

---

Note that there are some downsides to directly exposing this sort of metadata in attributes of your infrastructure objects.

Most notably, if you do so broadly then it means that any change you make to your configuration would presumably lead to Terraform proposing to update-in-place most or all of the resource instances declared in your configuration. That would mean a particularly noisy diff that might make it harder to see the more significant changes the Terraform providers are proposing to make.

If you choose to do this, I would recommend exposing it only in a single location in your configuration, rather than populating tags across all of your infrastructure objects. For example, you could write the information into an output value and then you can use `terraform output` to view the most recent values for your root module output values as recorded in the Terraform State, and then the "noisy" change for each new commit would only be to modify a small number of output values, and not to make changes to any real infrastructure.
Provided that `jq` and `git` commands are available, one can use the [`external` data source](https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/data_source) to fetch the required information. It requires output in json - a map of `string` to `string`. This is then available as the `result` property in a structured way. You can also add other contextual information, such as gitlab pipeline information.

Consider that this will trigger a change almost every time so use the frequently changing info sparingly. I tag the main resource group only.

Consider the warning - external data source is an escape hatch. You'd better be certain that the tools behave the same everywhere you run this Terraform configuration.

```
data "external" "git" {
  program = ["sh", "-c", <<-EOSCRIPT
    jq -n '{ "rev": $REV, "ref": $REF, "status": $STT, "clean": $CLN, "user": $USR, "repo": $REP, "job": $JOB, "pipeline": $PIP }' \
      --arg REV "$(git rev-parse --verify HEAD)" \
      --arg REF "$(git symbolic-ref HEAD || echo '(DETACHED)')" \
      --arg STT "$(git diff --quiet && echo "# CLEAN" || git status --porcelain)" \
      --arg CLN "$(git diff --quiet && echo yes || echo no)" \
      --arg USR "\"$${GITLAB_USER_LOGIN:-$(git config user.name)}\" <$${GITLAB_USER_EMAIL:-$(git config user.email)}>" \
      --arg REP "$(git remote get-url origin)" \
      --arg JOB "$CI_JOB_URL" \
      --arg PIP "$CI_PIPELINE_URL"
  EOSCRIPT
  ]
}
// short cut for easier use
// usage: local.git.rev
locals {
  git = data.external.git.result
}
// for information
output "git" {
  value = local.git
}

```

This code takes care of escaping so you don't run into issues with invalid JSON or poorly formatted command line. Terraform produces neat error feedback when something goes wrong with the commands: