Skip to main content Git & GitHub: The Foundation Your Whole Team Builds On | works-on-my.cloud
Series: aws-for-startups • Part 6 of 8

Git & GitHub: The Foundation Your Whole Team Builds On

• 11 min read
aws devops startup git
Table of Contents

Your agent commits a massive change with the message “updated files.” The diff includes 47 files: your Terraform module, an unrelated README tweak, a debug console.log, and your .env file with an AWS secret key. git add . strikes again. Except this time, it happened at 3 AM while you slept, because you gave the agent access to your repo.

When agents write code, your git hygiene matters more, not less. Bad habits that cost a human developer 10 minutes of cleanup cost an agent-accelerated workflow hours of forensic archaeology.

Time: About 30 minutes.

Outcome: A git workflow with conventional commits, branch naming conventions, agent attribution via Co-Authored-By, and a review process that treats agent PRs differently from human PRs. Plus 6 new lines in your AGENT-INSTRUCTIONS.md.


Why This Matters

You already have infrastructure in place. Part 1 locked down your AWS account. Part 4 gave you Terraform managing state. Part 5 set up observability. All of it lives in a git repository.

Without conventions, that repository becomes a liability. Here is what happens:

  • No branch strategy: everyone pushes to main. Terraform state drifts because two people ran apply on conflicting changes.
  • No commit conventions: the git log reads like a stream of consciousness. “fix stuff”, “wip”, “asdf”, “updated files.” Good luck understanding what changed three weeks ago.
  • No agent attribution: you cannot tell which commits came from a human and which came from an agent. When a security issue surfaces, you cannot trace whether a human reviewed the change or an agent shipped it directly.

Agents amplify every one of these problems. A human commits once or twice a day. An agent can commit 50 times in an hour. Without guardrails, that is 50 opportunities for leaked credentials, overly broad IAM policies, and undocumented infrastructure changes.

The conventions we set up here feed directly into the Scorecard (starting in Part 8). Agent attribution is not just for credit. It is data.


What We’re Building

  • Branch naming convention (feature/, fix/, chore/)
  • Conventional commit format with enforced types
  • Agent attribution via Co-Authored-By trailers
  • A .gitignore that protects against the most common agent mistakes
  • A PR template with an agent-review section
  • 6 new rules in AGENT-INSTRUCTIONS.md

Branching Strategy

Trunk-based development with short-lived feature branches. That is it. No develop branch. No release/v2.3.1 branches living for weeks. No git-flow ceremony that exists to justify its own complexity.

The rules:

RuleConvention
Main branchmain (always deployable)
Feature workfeature/add-vpc-module
Bug fixesfix/iam-policy-wildcard
Maintenancechore/update-terraform-providers
Documentationdocs/add-runbook-rds-failover

Branch names are lowercase, hyphen-separated, and descriptive. The prefix tells you the intent before you read the diff.

Agent branches follow the same naming. There is no agent/ prefix. The agent is a tool, not a separate team. Attribution happens at the commit level, not the branch level. This matters because it keeps your branch namespace clean and avoids the temptation to skip review on “agent branches.”

# Good
git checkout -b feature/add-s3-lifecycle-rules
git checkout -b fix/security-group-ingress-cidr
git checkout -b chore/bump-aws-provider-5.80

# Bad
git checkout -b new-stuff
git checkout -b agent-changes
git checkout -b test123

Lifecycle: branches live for hours or days, not weeks. If a branch is open for more than 3 days, it is too large. Break it into smaller changes. This is especially true for agent-generated work, because large agent PRs are nearly impossible to review effectively.


Conventional Commits

Every commit message follows this format:

type(scope): description

[optional body]

[optional footer(s)]

Types:

TypeWhen to useExample
featNew functionalityfeat(vpc): add NAT gateway to private subnets
fixBug fixfix(iam): remove wildcard resource from deploy role
choreMaintenance, dependencieschore(terraform): bump AWS provider to 5.80.0
docsDocumentation onlydocs(runbook): add RDS failover procedure
refactorCode change that neither fixes nor addsrefactor(modules): extract common tags to locals
testTests onlytest(vpc): add validation for CIDR block ranges

Scope is optional but valuable. Use the module, service, or domain name: vpc, iam, s3, ci, api.

Description is imperative mood, lowercase, no period. “add NAT gateway” not “added NAT gateway” or “Adding NAT gateway.”

Why Bother?

Conventional commits are not bureaucracy. They give you three things:

  1. Automated changelogs. Tools like conventional-changelog or release-please generate changelogs from commit history. No more manually writing “what changed this sprint.”
  2. Searchable history. git log --grep="^fix(iam)" shows every IAM fix. Try doing that with “fixed stuff.”
  3. Scorecard data. Starting in Part 8, your Agent Scorecard tracks commit types by author. You will see patterns: “agents generate 80% feat commits but only 5% test commits.” That is a signal.

Enforcing Locally

Install commitlint to reject non-conforming commit messages:

npm install --save-dev @commitlint/cli @commitlint/config-conventional
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      ['feat', 'fix', 'chore', 'docs', 'refactor', 'test', 'ci', 'perf'],
    ],
    'scope-case': [2, 'always', 'kebab-case'],
    'subject-case': [2, 'never', ['start-case', 'pascal-case', 'upper-case']],
    'header-max-length': [2, 'always', 100],
  },
};

Wire it into a git hook (we will do this properly with pre-commit in Part 8):

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

Now try a bad commit message:

git commit -m "updated files"
⧗   input: updated files
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

✖   Found 2 problems, 0 warnings

Good. The guardrail works for humans and agents alike.


Agent Commit Hygiene

This is the section that separates “using agents” from “using agents safely.” Three rules, no exceptions.

Rule 1: Never git add .

git add . and git add -A stage everything in the working directory. For a human, this might include a stray file or two. For an agent that has been generating, testing, and iterating, this can include:

  • .env files with real credentials
  • Debug logs and temporary test outputs
  • Build artifacts and node_modules changes
  • Unrelated files the agent touched while exploring

Always stage specific files:

# Good
git add modules/vpc/main.tf modules/vpc/variables.tf modules/vpc/outputs.tf

# Bad
git add .
git add -A
git add --all
🚨 Agent Trap

Agents default to git add . because it is the fastest path to a clean working tree. The agent’s goal is “commit the code,” not “commit only the relevant code.” This is Context Amnesia (category 5): the agent forgets you told it to only stage specific files three messages ago.

What catches it: The pre-commit hooks we add in Part 8 include a check for staged files that match .env*, *.log, and other patterns that should never be committed. But the first line of defense is the AGENT-INSTRUCTIONS.md rule we add at the end of this post.

Rule 2: Agent Attribution

Every agent-generated commit includes a Co-Authored-By trailer:

git commit -m "$(cat <<'EOF'
feat(vpc): add NAT gateway with cost-optimized single-AZ config

Single NAT gateway in us-east-1a. Multi-AZ NAT is $65/month per
additional gateway — not justified until traffic exceeds 100GB/month
cross-AZ.

Co-Authored-By: Claude <noreply@anthropic.com>
EOF
)"

For GitHub Copilot:

Co-Authored-By: GitHub Copilot <noreply@github.com>

For Cursor:

Co-Authored-By: Cursor <noreply@cursor.com>

Why this matters:

  • GitHub recognizes Co-Authored-By trailers and shows them in the commit UI
  • git log --grep="Co-Authored-By: Claude" gives you every agent-generated commit instantly
  • The Scorecard (Part 8+) uses this data to track agent contribution quality over time
  • When a security audit asks “who wrote this IAM policy,” you have a clear answer

Rule 3: One Logical Change Per Commit

Agents love to bundle. You ask for a VPC module and get back a VPC, three security groups, an ALB, a Route 53 record, and a “helpful” IAM policy with Action: "*". All in one commit.

Force atomic commits:

# One commit per logical unit
git add modules/vpc/main.tf modules/vpc/variables.tf modules/vpc/outputs.tf
git commit -m "feat(vpc): add VPC with public and private subnets"

git add modules/vpc/security-groups.tf
git commit -m "feat(vpc): add security groups for web and app tiers"

git add modules/vpc/nacls.tf
git commit -m "feat(vpc): add network ACLs for subnet-level filtering"

This makes code review possible. A 500-line commit across 15 files is a rubber-stamp invitation. Five 100-line commits with clear scopes get actual review.


The .gitignore That Saves You

A comprehensive .gitignore is your safety net for when git add . happens anyway (and it will). Here is what should be in yours for an AWS/Terraform/Node project:

# Credentials and secrets — NEVER commit these
.env
.env.*
!.env.example
*.pem
*.key
*credentials*
*secret*

# Terraform
.terraform/
*.tfstate
*.tfstate.*
*.tfplan
crash.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Terraform lock file — DO commit this
!.terraform.lock.hcl

# IDE and editor
.vscode/settings.json
.idea/
*.swp
*.swo
*~
.DS_Store

# Dependencies
node_modules/
.pnpm-store/

# Build outputs
dist/
build/
.next/
.astro/

# Logs
*.log
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*

# Agent artifacts
.agent-sessions/
.claude/
.cursor/
.copilot/
Note

Commit .env.example with placeholder values so new team members (and agents) know which variables are required. Never commit .env with real values.

The *credentials* and *secret* patterns are intentionally broad. False positives are better than leaked keys. If you have a file called secrets-architecture.md that you actually want to commit, add a specific exception.


Reviewing Agent PRs

Agent PRs are not human PRs. They require a different review lens.

When a human submits a PR, you review for logic, architecture, and edge cases. You trust that they did not hardcode credentials or add AdministratorAccess to an IAM role. (You still check, but it is not your primary concern.)

When an agent submits a PR, the checklist inverts:

Agent PR Review Checklist

CheckWhy
IAM permissionsAgents default to broad permissions. Look for Resource: "*", Action: "*", AdministratorAccess.
Resource namingDoes it follow {project}-{env}-{resource} from AGENT-INSTRUCTIONS.md?
Hardcoded valuesRegions, account IDs, AMI IDs, CIDR blocks. All should be variables or data sources.
Missing tagsEvery resource needs Environment, Project, Owner, ManagedBy.
Security group rulesIngress from 0.0.0.0/0? Only acceptable on ALB port 443.
Cost implicationsDid the agent choose t3.xlarge when t3.micro would work? Check instance types, storage sizes, reserved capacity.
Credentials in codeSearch the diff for anything that looks like a key, token, or password.

PR Template

Create a PR template that forces this review:

## Summary

<!-- What does this PR do? One paragraph. -->

## Generation Method

<!-- How was this code created? Check one. -->

- [ ] Fully human-written
- [ ] Human-written with agent suggestions (Copilot autocomplete, etc.)
- [ ] Agent-generated with human review (Claude, Cursor, etc.)
- [ ] Agent-generated with minimal review

## Changes

<!-- List the key changes -->

-

## Agent Review Checklist

<!-- Complete if any agent involvement -->

- [ ] IAM permissions follow least privilege
- [ ] No hardcoded account IDs, regions, or AMI IDs
- [ ] All resources have required tags
- [ ] Security group ingress rules are scoped
- [ ] No credentials or secrets in code
- [ ] Cost implications reviewed
- [ ] Commit messages follow conventional format
- [ ] Co-Authored-By attribution present on agent commits

## Testing

<!-- How was this tested? -->

-

The “Generation Method” section is critical. It tells the reviewer how much scrutiny to apply. A PR marked “Agent-generated with minimal review” gets a full manual review. A PR marked “Fully human-written” still gets the standard review, but the reviewer spends less time checking for agent-specific failure modes.

Note

Coming in Part 27: Your CI pipeline will automatically label PRs with agent attribution data from the commit trailers. No manual checkbox needed.


AGENT-INSTRUCTIONS.md Update

Add the Git Conventions section to the AGENT-INSTRUCTIONS.md you created in Part 1 and expanded in Part 4.

## Git Conventions

- Conventional commits required: feat:, fix:, chore:, docs:, refactor:, test:
- NEVER use `git add .` or `git add -A`
- Always `git add` specific files by name
- Branch naming: feature/, fix/, chore/, docs/
- One logical change per commit
- Always include Co-Authored-By trailer on agent-generated commits

Your AGENT-INSTRUCTIONS.md now has 21 lines: the header (1), IAM Rules from Part 2 (4), Terraform Conventions from Part 4 (10), and Git Conventions (6).

This file is the single source of truth for agent behavior in your repository. Every agent session should start by reading it. Every convention you add here is one fewer thing you need to catch in code review.

🚨 Agent Trap

Agents will acknowledge your AGENT-INSTRUCTIONS.md at the start of a conversation, then gradually forget its rules as the context window fills up. By message 15, the agent is back to git add . and generic commit messages. This is why automated enforcement (commitlint, pre-commit hooks) matters more than written rules alone. We add those automated guardrails in Part 8.


Your Repository Structure So Far

After Parts 1-6, your project should look like this:

your-project/ .github/ pull_request_template.md .husky/ commit-msg terraform/ environments/ dev/ main.tf observability.tf modules/ vpc/ signoz-ec2/ docker/ observability/ AGENT-INSTRUCTIONS.md .gitignore commitlint.config.js package.json


The Fine Line

⚠️ The Fine Line
❌ UnderNo conventions. git add ., commit messages like “wip” and “fix.” Agent commits undifferentiated from human commits. Three months later, a security audit asks who approved the IAM policy with AdministratorAccess and nobody knows.
✅ RightConventional commits enforced by commitlint. Specific file staging. Agent attribution via Co-Authored-By. PR template with generation method and agent review checklist.
❌ OverGPG signing required on every agent commit, automated squash policies that destroy commit history, mandatory 3-reviewer approval for any file an agent touched, separate repositories for agent-generated code.
🤖 Agent TrapAgent uses git add . because it is the shortest path to a clean working tree. The commit sweeps in .env with AWS credentials, a debug log with request payloads, and 12 unrelated files the agent modified while exploring. Your .gitignore catches the .env, but the debug log with customer data ships to GitHub.

What’s Coming

Next in Part 7: Branch Protection & PR Workflow, we add branch protection rules that prevent direct pushes to main, require PR reviews, and enforce status checks. The conventions you set up today become enforced policy.


Validation Checklist

Git Setup

Agent Workflow

AGENT-INSTRUCTIONS.md

0 of 0 completed


Key Takeaways

  1. git add . is the most dangerous command when agents write your code, because agents generate more stray files, faster, than any human.
  2. Conventional commits are not bureaucracy. They are structured data that feeds changelogs, enables git log queries, and powers the Agent Scorecard you build in Part 8.
  3. Agent attribution via Co-Authored-By is not about credit. It is about traceability: when something breaks, you need to know whether a human reviewed the change or an agent shipped it unchecked.
  4. Review agent PRs with a different lens: permissions, naming, hardcoded values, missing tags, cost implications. The default human trust assumptions do not apply.

Have questions? Found an error? Open an issue or reach out on LinkedIn.

Related Posts

Series • Part 1

Your First 60 Minutes in AWS: What Everyone Skips and Regrets Later

What everyone skips and regrets later. Set up your AWS account the right way: secure enough to sleep at night, without the enterprise overhead that kills velocity.

• 12 min read • aws • devops • startup
Series • Part 2

IAM: The Key to Everything

Least privilege without losing your mind. Build a working IAM setup for your startup, not enterprise complexity, not 'just use AdministratorAccess.' The practical middle ground.

• 26 min read • aws • iam • security
Series • Part 3

Your Local AWS Setup: Stop Hardcoding Access Keys Forever

Stop hardcoding access keys forever. Configure your local development environment the right way: AWS CLI, IAM Identity Center, and credential security that scales with your team.

• 14 min read • aws • cli • security
Series • Part 4

Terraform Fundamentals: Why Clicking Is Technical Debt

Stop clicking through the AWS console. Set up your Terraform project from scratch with remote state, proper structure, and templates for everything we've built so far.

• 15 min read • aws • terraform • iac
Series • Part 5

OpenTelemetry Setup: Observability That Grows With You

Set up the OTel Collector once, choose your backend. SigNoz or Grafana stack. Your observability foundation for the entire series.

• 16 min read • aws • opentelemetry • observability
Series • Part 7

Branch Protection & PR Workflow: Quality Gates for Humans and Agents

Quality gates that catch both human and agent mistakes. Branch protection, PR templates with agent-review sections, and CODEOWNERS for your growing team.

• 10 min read • aws • devops • startup
Series • Part 8

Pre-Commit Hooks & Code Quality: Your Agents' First Guardrail

Your agents' first guardrail, and your Scorecard's first data source. Pre-commit hooks that catch what human review misses, especially from AI-generated code.

• 20 min read • aws • devops • startup
Published: January 28, 2026