Merge, Tag, and Release: Keeping Track of What Goes to Production
You just finished reviewing a pull request. The code looks good, the tests pass, and your teammate approved the changes. Now what?
Most teams know they need to merge the changes into the main branch. But the way you merge, the records you leave behind, and how you mark what's running in production all determine whether your team can answer a simple question six months from now: "What code was actually deployed on that date?"
The Merge Commit Is Your Paper Trail
There are several ways to combine changes from a feature branch into your main branch. The most common approach is creating a merge commit.
A merge commit does more than just move code. It records two pieces of information: which branch the changes came from, and which branch they went into. This creates a clear entry in your commit history that says, "Something was merged here."
Compare this with a fast-forward merge, where Git simply moves the pointer forward without creating a new commit. Fast-forward merges keep the history linear, but they lose the context that a merge happened. If you later need to trace a bug back to its source, a merge commit gives you a direct link to the pull request discussion, the review comments, and the exact changes that came together.
When you use merge commits, your git log tells a story. You can see that feature-x was merged into main on Tuesday, and feature-y was merged on Wednesday. If something breaks on Thursday, you know exactly which merge to investigate first.
The following flowchart shows how each step connects to create a clear paper trail:
Here is the exact sequence of commands to follow after a pull request is approved:
# 1. Merge with a non-fast-forward merge commit
git checkout main
git merge --no-ff feature-x -m "Merge feature-x into main"
# 2. Tag the release on the merge commit
git tag -a v1.2.3 -m "Release v1.2.3"
# 3. Push main and the new tag to the remote
git push origin main --tags
# 4. Delete the feature branch locally and remotely
git branch -d feature-x
git push origin --delete feature-x
Clean Up After the Merge
Once the merge is complete, the feature branch has served its purpose. Deleting it keeps your repository tidy and prevents old branches from cluttering the list when someone needs to create a new one.
Some teams delete branches immediately after merging. Others wait until the new version has been running in production for a day or two, just in case they need to create a hotfix branch from the same point. Either approach works, as long as you have a consistent practice.
Before deleting, make sure all changes from that branch are actually in the main branch. A quick check: if the branch has been merged via pull request, most Git hosting platforms will show it as "merged" and allow one-click deletion.
Tags: Giving Names to Versions
Your main branch now contains the latest code. But how do you know exactly which commit is running in production right now? The main branch keeps moving forward as new changes come in. Without a fixed reference point, you're guessing.
This is where tags come in. A tag is a label attached to a specific commit. Unlike branches, tags don't move. Once you create a tag, it points to that exact commit forever.
Teams typically create tags when they release a new version. For example, after testing is complete and the team is ready to deploy to production, they create a tag like v1.2.0 on the last commit of the main branch. That tag becomes a permanent reference. Six months later, if someone asks what code was running on that date, you check the tag.
Naming Your Tags Consistently
Tag names should follow a convention that everyone on the team understands. Semantic versioning is a popular choice: v1.2.3 where:
- The first number changes for major releases that break backward compatibility
- The second number changes for new features
- The third number changes for bug fixes and small improvements
But semantic versioning isn't the only option. Some teams use dates: release-2024-11-15. Others use build numbers: build-142. The important thing is consistency. Pick a format, document it, and use it for every release.
Whatever format you choose, make sure the tag is created from the exact commit that was deployed. If you tag a different commit, the tag loses its value as a reliable reference point.
Release Notes: What Changed and Why
After creating a tag, most teams write release notes. A release note is a short summary of what changed in this version. It doesn't need to be long or detailed. It just needs to answer the question: "Should I care about this release?"
Good release notes include:
- New features that users will notice
- Bug fixes that resolve known issues
- Breaking changes that require action from other teams or users
- Known issues or limitations in this version
Release notes don't have to be written from scratch. Many teams generate them from the pull request titles or commit messages between the last tag and the current one. A quick review to remove technical details and add user-facing context is usually enough.
The Bridge Between Development and Production
Merge and tagging form the bridge between writing code and running it in production. The merge ensures that reviewed changes enter the shared codebase. The tag ensures that you can point to a specific commit and say, "This is the version running right now."
Without tags, you have a long commit history and no way to know which commits were actually released. You end up guessing, checking deployment logs, or asking teammates who might not remember. Tags eliminate that uncertainty.
Practical Checklist
Before your next release, run through these steps:
- Merge the pull request with a merge commit, not fast-forward
- Delete the feature branch after confirming the merge
- Create a tag on the exact commit that will be deployed
- Write release notes covering what changed and why it matters
- Confirm the tag is pushed to the remote repository so the whole team can see it
What This Means for Your Team
The next time you merge a pull request, think about what you're leaving behind. A merge commit and a tag are small actions, but they create a history that your future self will thank you for. When something goes wrong at 2 AM and you need to know what changed, you won't have to guess. You'll have a clear trail from the production issue back to the merge commit, the pull request, and the discussion that led to the change.