> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/argoproj/argo-cd/llms.txt
> Use this file to discover all available pages before exploring further.

# Tracking Strategies

> Learn how Argo CD tracks Git revisions and Kubernetes resources

Argo CD provides flexible strategies for tracking application sources and deployed resources. Understanding these strategies helps you implement effective deployment workflows for different environments.

## Git Tracking Strategies

Argo CD supports multiple ways to track your Git repository, each suited for different use cases.

### HEAD / Branch Tracking

Track the tip of a branch for continuous deployment:

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: main  # or HEAD
    path: manifests
```

**Use cases:**

* Development environments
* Continuous deployment pipelines
* Automatic updates on every commit

**How it works:**
Argo CD continuously monitors the branch and compares live state against the latest commit. Any new commit triggers a comparison (and sync if auto-sync is enabled).

<Info>
  With auto-sync enabled, every push to the tracked branch automatically deploys to your cluster.
</Info>

### Tag Tracking

Track a specific Git tag for more stable deployments:

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: v1.2.3
    path: manifests
```

**Use cases:**

* Staging environments
* Release-based deployments
* Controlled updates

**How it works:**
Argo CD uses manifests at the specified tag. To deploy a new version, retag or change the Application's `targetRevision`.

<Note>
  If you retag the same tag name to a different commit, Argo CD will detect the change and sync accordingly.
</Note>

### Semantic Version Ranges

Automatically track the latest version within a range:

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: 1.2.*  # Tracks latest 1.2.x version
    path: manifests
```

**Version range examples:**

| Use Case             | Range                       | Example Matches                    |
| -------------------- | --------------------------- | ---------------------------------- |
| Pin to version       | `1.2.3`                     | Only 1.2.3                         |
| Track patches        | `1.2.*` or `>=1.2.0 <1.3.0` | 1.2.0, 1.2.1, 1.2.5                |
| Track minor releases | `1.*` or `>=1.0.0 <2.0.0`   | 1.0.0, 1.5.2, 1.9.0                |
| Use latest           | `*` or `>=0.0.0`            | All stable versions                |
| Include prereleases  | `*-0` or `>=0.0.0-0`        | All versions including alpha, beta |

<Warning>
  By default, prerelease versions (alpha, beta, rc) are excluded. Use the `-0` suffix to include them.
</Warning>

**Examples:**

```yaml theme={null}
# Production: Pin to specific version
targetRevision: 2.1.0

# Pre-production: Track patch releases
targetRevision: 2.1.*

# QA: Track minor releases
targetRevision: 2.*

# Development: Use latest including prereleases
targetRevision: "*-0"
```

### Commit SHA Pinning

Pin to a specific commit for maximum control:

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: 9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b
    path: manifests
```

**Use cases:**

* Production environments
* Strict change control
* Compliance requirements

**How it works:**
Commit SHAs are immutable. The only way to change deployment is to update the Application's `targetRevision` to a different commit SHA.

<Info>
  [Parameter overrides](https://argo-cd.readthedocs.io/en/stable/user-guide/parameters/) still apply even with commit pinning.
</Info>

### Handling Ambiguous Git References

When a branch and tag share the same name, use fully-qualified references:

**Problem scenario:**

```
refs/heads/release-1.0 -> commit B
refs/tags/release-1.0  -> commit A
```

If `targetRevision: release-1.0`, Argo CD may resolve to either commit, causing reconciliation loops.

**Solution: Use fully-qualified references:**

```yaml theme={null}
# For branch
targetRevision: refs/heads/release-1.0

# For tag
targetRevision: refs/tags/release-1.0
```

<Warning>
  Avoid using the same name for branches and tags to prevent ambiguity.
</Warning>

## Helm Chart Tracking

Helm charts use semantic versioning:

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
spec:
  source:
    repoURL: https://charts.example.com
    chart: my-app
    targetRevision: 1.2.*  # Track patches
    helm:
      releaseName: my-app
```

**Version tracking examples:**

```yaml theme={null}
# Pin to exact version (production)
targetRevision: 1.2.3

# Track patch updates (staging)
targetRevision: 1.2.*

# Track minor updates (QA)
targetRevision: 1.*

# Use latest stable
targetRevision: "*"

# Include prereleases
targetRevision: "*-0"
```

## Resource Tracking Methods

Argo CD tracks deployed resources using labels or annotations.

### Annotation-Based Tracking (Default)

Uses the `argocd.argoproj.io/tracking-id` annotation:

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  namespace: default
  annotations:
    argocd.argoproj.io/tracking-id: my-app:apps/Deployment:default/my-deployment
spec:
  # ...
```

**Advantages:**

* No conflicts with other tools
* No 63-character truncation limit
* Clear ownership per Argo CD instance

**Configure in `argocd-cm`:**

```yaml theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  application.resourceTrackingMethod: annotation
```

### Annotation + Label Tracking

Uses annotation for tracking, adds label for compatibility:

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  namespace: default
  labels:
    app.kubernetes.io/instance: my-app  # For tool compatibility
  annotations:
    argocd.argoproj.io/tracking-id: my-app:apps/Deployment:default/my-deployment  # For tracking
spec:
  # ...
```

**Configure:**

```yaml theme={null}
data:
  application.resourceTrackingMethod: annotation+label
```

<Info>
  The label is informational only and truncated if longer than 63 characters. Tracking uses the annotation.
</Info>

### Label-Based Tracking (Legacy)

Uses the `app.kubernetes.io/instance` label:

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
  namespace: default
  labels:
    app.kubernetes.io/instance: my-app
spec:
  # ...
```

**Limitations:**

* 63-character label limit
* Potential conflicts with other tools
* Difficult to run multiple Argo CD instances

**Configure:**

```yaml theme={null}
data:
  application.resourceTrackingMethod: label
```

### Custom Label

Use a custom label instead of the default:

```yaml theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  application.instanceLabelKey: argocd.argoproj.io/instance
```

## Installation ID

Run multiple Argo CD instances on the same cluster:

```yaml theme={null}
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  application.resourceTrackingMethod: annotation
  # Unique identifier for this Argo CD instance
  argocd.argoproj.io/installation-id: production-argocd
```

**Benefits:**

* Each resource gets: `argocd.argoproj.io/installation-id: production-argocd`
* Prevents conflicts between instances
* Allows multiple apps with the same name

## Non-Self-Referencing Annotations

When using annotation-based tracking, resources can be copied to other namespaces without affecting sync status:

```yaml theme={null}
# Original resource in namespace 'default'
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
  namespace: default
  annotations:
    argocd.argoproj.io/tracking-id: my-app:/ConfigMap:default/my-config
data:
  key: value
```

If a tool copies this to namespace `other`:

```yaml theme={null}
# Copied resource in namespace 'other'
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
  namespace: other  # Different namespace
  annotations:
    argocd.argoproj.io/tracking-id: my-app:/ConfigMap:default/my-config  # Still references 'default'
data:
  key: value
```

Argo CD won't track the copied resource because the tracking annotation references a different namespace.

## Tracking Strategy Examples

### Development Environment

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-dev
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: HEAD  # Always latest
    path: manifests/dev
  
  destination:
    server: https://kubernetes.default.svc
    namespace: dev
  
  syncPolicy:
    automated:
      enabled: true
      prune: true
      selfHeal: true  # Auto-fix manual changes
```

### Staging Environment

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-staging
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: 1.2.*  # Track patch releases
    path: manifests/staging
  
  destination:
    server: https://kubernetes.default.svc
    namespace: staging
  
  syncPolicy:
    automated:
      enabled: true
      prune: true
```

### Production Environment

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-prod
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: v1.2.3  # Pinned version
    path: manifests/prod
  
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  
  # Manual sync only
  syncPolicy: {}
```

### Helm Chart with Version Range

```yaml theme={null}
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx-ingress
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://kubernetes.github.io/ingress-nginx
    chart: ingress-nginx
    targetRevision: 4.7.*  # Track patches in 4.7.x
    helm:
      releaseName: nginx-ingress
      parameters:
      - name: controller.service.type
        value: LoadBalancer
  
  destination:
    server: https://kubernetes.default.svc
    namespace: ingress
  
  syncPolicy:
    automated:
      enabled: true
```

## Automatic Sync Behavior

With [auto-sync](https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/) enabled:

```yaml theme={null}
syncPolicy:
  automated:
    enabled: true
    prune: true
    selfHeal: true
```

**Sync triggers:**

* New commit to tracked branch
* Tag update (if tracking a tag)
* New version matching semantic range
* Manual changes in cluster (if `selfHeal: true`)

**Sync semantics:**

* Only syncs when OutOfSync
* Won't retry if previous sync to same commit failed
* Retries after self-heal timeout (5s default) if `selfHeal: true`

<Note>
  Parameter overrides always take precedence over Git state.
</Note>

## Changing Tracking Methods

To switch tracking methods:

1. Update `argocd-cm` ConfigMap:
   ```yaml theme={null}
   data:
     application.resourceTrackingMethod: annotation  # or annotation+label, label
   ```

2. Sync all applications to apply new tracking method:
   ```bash theme={null}
   argocd app sync --all
   ```

3. Argo CD will add the new tracking identifier to resources

<Info>
  You can safely revert to a previous tracking method by updating the ConfigMap and re-syncing.
</Info>

## Best Practices

<CardGroup cols={2}>
  <Card title="Match Strategy to Environment" icon="layer-group">
    Use HEAD for dev, ranges for staging, pins for production
  </Card>

  <Card title="Use Annotation Tracking" icon="bookmark">
    Avoid label conflicts and truncation issues
  </Card>

  <Card title="Avoid Ambiguous References" icon="diamond-exclamation">
    Don't use same name for branches and tags
  </Card>

  <Card title="Semantic Versioning" icon="code-branch">
    Use semver tags for predictable version tracking
  </Card>
</CardGroup>

## Troubleshooting

### Application Not Detecting Changes

1. Verify target revision:
   ```bash theme={null}
   argocd app get my-app
   ```

2. Check if tracking a branch:
   ```bash theme={null}
   git rev-parse origin/main
   ```

3. Force refresh:
   ```bash theme={null}
   argocd app refresh my-app
   ```

### Resources Not Tracked

1. Check tracking annotation:
   ```bash theme={null}
   kubectl get deployment my-app -o yaml | grep tracking-id
   ```

2. Verify tracking method in ConfigMap:
   ```bash theme={null}
   kubectl get configmap argocd-cm -n argocd -o yaml | grep resourceTrackingMethod
   ```

3. Re-sync application to apply tracking:
   ```bash theme={null}
   argocd app sync my-app
   ```

### Version Range Not Working

1. Verify tags exist:
   ```bash theme={null}
   git ls-remote --tags https://github.com/example/app.git
   ```

2. Check if tags are semver:
   ```bash theme={null}
   # Valid: v1.2.3, 1.2.3
   # Invalid: release-1.2.3
   ```

3. Include prereleases if needed:
   ```yaml theme={null}
   targetRevision: "1.2.*-0"
   ```

## Next Steps

<CardGroup cols={2}>
  <Card title="Sync Options" icon="sliders" href="/applications/sync-options">
    Configure how applications sync
  </Card>

  <Card title="Sync Waves" icon="wave-pulse" href="/applications/sync-waves">
    Control deployment order
  </Card>

  <Card title="Creating Apps" icon="plus" href="/applications/creating-apps">
    Learn how to create applications
  </Card>

  <Card title="Health Checks" icon="heart-pulse" href="/applications/health-checks">
    Monitor application health
  </Card>
</CardGroup>
