The skills library is open: 86 files, one email

Version Control for Marketing Copy: The Repository Layout and the Review That Holds

What belongs in a marketing repository and what does not, a directory structure that survives a real team, and the pull request that makes review worth doing.

Mert · Founder7 min read
Post Share

A marketer changes a headline on the pricing page at 11am. Conversion drops eighteen per cent over the next fortnight. Nobody notices until the monthly review, and by then the question is not "what happened" but "what did it say before". The CMS keeps one revision, the Google Doc was edited in place by four people, and the person who made the change is on leave.

That is a storage problem, not a discipline problem. Marketing teams keep their most valuable assets in systems that overwrite rather than append. The overview of marketing as code makes the general case; this is the layout and the review process in detail.

Text, rules and definitions go in; binaries and personal data stay out

The test: would you want to read a line-by-line diff of this changing, and could a reviewer judge it? If yes, it goes in, and that covers more than people expect. Messaging and positioning documents, because they change quietly and nobody can say when. Ad variants, one file each with headline, description, destination and audience as structured fields. Email sequences as definitions: touches, delays, exit conditions, suppression rules. Landing page copy, section by section. Signal rules, ICP definitions and the tracking plan, which are the documents most likely to exist in four contradictory versions across a stack.

What stays out matters more, because the wrong thing in a repository is worse than nothing. Design binaries do not belong: a 40MB layered file makes every clone slow forever and the diff is unreadable anyway. Personal data stays out absolutely, including the export you pasted in to test an audience rule. Git history is effectively permanent, deletion does not remove it from earlier commits, and a repository with names and email addresses in its history is a deletion request you cannot service. Credentials stay out too, enforced by a secret scanner rather than good intentions.

A structure that survives contact with a real team

/context/          company.md  icp.md  product.md  proof.md  voice.md
/messaging/        positioning.md  narratives/  objections.md
/campaigns/
  2026-q3-dach-launch/
    brief.md
    ads/            li-single-01.md  go-rsa-01.md
    landing/        hero.md  proof.md  faq.md
    email/          seq-01-touch-1.md ... touch-5.md
    audiences/      icp-tier-1.sql
/rules/            scoring.yaml  routing.yaml  signals.yaml
/tracking/         plan.yaml  dictionary.md
/checks/           banned-claims.txt  approved-claims.md

Two decisions in that tree do the work. Context files sit at the root rather than inside a campaign, because every campaign reads them and a copy inside a campaign folder drifts within a month. Campaigns are dated folders, because that is how a human finds the thing they half remember from last spring.

One file per ad variant looks wasteful and is not. Each gets a stable identity, an author, a date and a history that spreadsheet rows cannot.

A branch per campaign beats a branch per person

The instinct is sarah/ad-copy, because that is how developers work. It is wrong here: a branch named for a person accumulates unrelated changes. Sarah's branch ends up holding a new ad variant, a fix to the tracking plan and half a rewritten sequence, so the pull request cannot be reviewed as one decision and cannot be reverted as one either. A branch named campaign/2026-q3-dach-launch has a subject: everything on it serves one goal, and reverting it removes the campaign rather than whatever Sarah touched that week.

Use fix/ for corrections to something already live and content/ for standalone work. Three prefixes, no more. Conventions with six categories are abandoned by week four.

The pull request has four parts, and three of them are not the diff

A pull request that only shows a diff wastes the review. A template should ask for four things.

The change, in one plain sentence. "Replacing the hero headline on the pricing page and adding a proof point below the fold."

The reason, and the evidence. "August call reviews show three prospects asking whether the price includes implementation, and the headline does not answer it."

The metric it should move, with a direction and a window. "Pricing page to demo request, currently 4.1 per cent, over twenty business days." This field causes arguments, which is the point. A change nobody can attach a metric to is usually one nobody has thought about. It may still merge, but it has to say "no measurable effect expected, consistency fix" out loud.

The rollback. For a page, reverting the commit is enough. For an ad set already in the learning phase, reverting the copy does not undo the spend or reset the algorithm, so the note has to state the real remedy.

Review is a routing problem, not a queue behind one person

The failure mode is predictable. Everything goes to the head of marketing, who is in meetings, and a fourteen-word ad headline waits three days. Within a month people ship outside the process, and the repository records what was approved rather than what is live.

Route by type of claim instead. Pricing, security and regulatory claims go to whoever owns that ground and nobody else. Product capability claims go to product marketing. Everything else is a style and clarity review, and any two people on the team can do it. In GitHub this is a CODEOWNERS file, which requests the right reviewer automatically when a matching path changes.

Then state a latency: ad variants and email touches within one working day, positioning and pricing within three. The number is what lets people escalate instead of quietly routing around the process.

Nobody has to open a terminal

The objection you will hear is that marketers will not use Git, and it mostly answers a question nobody asked. Editing a file in GitHub's web editor and proposing a change creates a branch and a pull request without either word appearing. Reviewing is reading a side-by-side and typing a comment. That is the entire interaction for most of the team.

Real fluency is needed only by the one or two people building the checks and the deploys. For everyone else, write a one-page guide with screenshots of the three things they will actually do. The GitHub Engine is this running as a system, including the parts that keep non-technical contributors out of the command line.

Where this genuinely fails

Fast-moving social is the clearest case. If your team responds to a trend within ninety minutes, a review gate is a loss rather than a control. Carve social out, give it a named owner with authority to publish, and record what went out afterwards rather than approving it beforehand. A process people must break to do their job teaches them to break it everywhere else.

Anything needing a designer in the loop fails differently. Layout, crop and type treatment happen in a design tool, and approving text while the composition is still moving approves half a thing. Either accept that design review is separate, or delay the merge until the asset is final. Pretending the diff covers the creative is the mistake.

Below about four people it is mostly overhead. Two marketers in the same room already have a review process, and it is called talking. The repository starts paying when no single person can hold the current state in their head: an agency, a contractor, a product marketer and a demand gen lead all touching copy in one fortnight. At that size the only question left is how quickly you can get it set up.

Frequently asked questions

What should a marketing team keep in a Git repository?

Anything that is text, structured data or a rule, and whose change you would want to read as a diff: messaging and positioning documents, ad variants, email sequence definitions, landing page copy, signal and scoring rules, ICP definitions, and the tracking plan. Keep out design binaries, large media, credentials, and anything containing personal data, since Git history is permanent and a deletion request cannot be serviced against it.

How should marketing branches be named?

Name branches for the campaign rather than the person: campaign/2026-q3-dach-launch rather than sarah/ad-copy. A campaign branch has one subject, so the pull request is reviewed as one decision and reverted as one unit. A personal branch accumulates unrelated changes and cannot be rolled back cleanly.

What should a marketing pull request contain?

The change in one plain sentence, the reason and evidence behind it, the metric it should move with a direction and a window, and the rollback plan if it performs badly. The metric field does the most work, because a change nobody can attach a metric to is usually one nobody has thought through. Changes with no expected measurable effect are fine, provided the pull request says so.

Do marketers need to learn Git to work this way?

Most do not. Editing a file in a web interface, proposing the change and reviewing a side-by-side diff with comments covers the entire interaction for most of a marketing team, and none of it needs a terminal. Only the one or two people building the automated checks and the deploy pipeline need real fluency.

see where you stand

Twelve questions. Then your build order.

The diagnostic returns your operating stage, the three widest gaps in your motion and what to build first. Two minutes, no sales sequence, one human reply.

Keep reading

All articles →