Git and Version Control
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Mastering Version Control: The Foundation of Deployment and Automation
Introduction: Why Version Control is Non-Negotiable
In the world of modern software development and infrastructure management, the ability to track, manage, and collaborate on code is not just a helpful practice—it is the bedrock of everything we do. Version control is the systematic process of recording changes to a file or set of files over time so that you can recall specific versions later. In the context of deployment provisioning and automation, version control is the "single source of truth." When you are provisioning servers, deploying applications, or writing automation scripts, you need a way to ensure that the environment you are building today is consistent with the one you built yesterday, and that any changes made can be audited, rolled back, or peer-reviewed.
Without version control, teams are forced to rely on manual file naming conventions like config_final_v2_fixed.yaml, which is a recipe for disaster. This leads to configuration drift, where the state of your infrastructure becomes unpredictable because no one can definitively say which version of a configuration file is actually running in production. By adopting Git—the industry-standard distributed version control system—you bring discipline, transparency, and safety to your automation workflows. This lesson will guide you through the fundamental mechanics of Git, how to integrate it into your provisioning pipelines, and the best practices required to keep your automation code maintainable and error-free.
Understanding the Git Architecture
To use Git effectively, you must understand that it is not just a "save button" for your code. Git is a distributed version control system, meaning every developer or automation server has a full copy of the project history. This architecture is what makes Git so resilient; if a central server goes down, you still have the entire history of the project on your local machine.
The Three States of Git
When working with files in a Git repository, your files reside in one of three states:
- Modified: You have changed the file but have not yet committed it to your database.
- Staged: You have marked a modified file in its current version to go into your next commit snapshot.
- Committed: The data is safely stored in your local database.
Understanding these states is crucial for automation engineers. For instance, when you are modifying a Terraform script to add a new security group, you might change multiple files. You must explicitly "stage" these changes before committing them. This allows you to group logical changes together—like adding a new network subnet and its corresponding route table—into a single, atomic commit that represents a complete unit of work.
Callout: Centralized vs. Distributed Version Control In centralized systems (like Subversion), there is one server that holds the version history, and clients check out a single version. If the server is inaccessible, you cannot commit or view history. In a distributed system like Git, every user has the entire history. This allows for offline work, faster branching, and significantly more robust data integrity.
Setting Up Your Git Environment
Before you can automate deployments, you need a properly configured Git environment. Most Linux-based automation servers come with Git pre-installed, but it is important to ensure your identity is configured so that every change is attributed to the correct author.
Step-by-Step Configuration
- Install Git: On Ubuntu/Debian, use
sudo apt update && sudo apt install git. For RHEL/CentOS, usesudo yum install git. - Set Identity: Git needs to know who you are. This information is attached to your commits.
git config --global user.name "Your Name" git config --global user.email "[email protected]" - Verify Configuration: Run
git config --listto ensure your settings are correct.
Tip: Always use your corporate email address if you are working on professional projects. This ensures that your commits are correctly linked to your identity in platforms like GitHub, GitLab, or Bitbucket, which is essential for audit trails.
Core Git Commands for Automation Workflows
Automation engineers spend most of their time interacting with the repository through a handful of specific commands. Mastering these will make your daily workflow much faster and less prone to errors.
1. Initializing and Cloning
If you are starting a new project, use git init. If you are working on an existing infrastructure repository, you will use git clone.
# Clone an existing repository to your local machine
git clone https://github.com/your-org/infrastructure-code.git
2. Tracking Changes
After modifying a configuration file, use git status to see what has changed. This is the most important command for keeping your workspace clean.
git status
Output will show files that are untracked (new files), modified (existing files changed), or staged.
3. Staging and Committing
Staging is the process of preparing files for a snapshot. Committing creates the snapshot.
# Stage a specific file
git add main.tf
# Stage all changes in the current directory
git add .
# Commit with a descriptive message
git commit -m "Add production database security group rules"
Warning: Avoid using
git add .blindly. Always rungit statusfirst to ensure you aren't accidentally adding sensitive files like.envfiles containing API keys or private SSH keys.
Branching: The Secret to Safe Deployments
One of the biggest mistakes in infrastructure automation is working directly on the main or master branch. If you push a broken configuration to the main branch, you could accidentally trigger an automated deployment that crashes your entire production environment.
The Feature Branch Workflow
The industry standard is to use "feature branches." When you need to update a server configuration, you create a new branch, make your changes, test them, and then merge them back into the main branch.
- Create a branch:
git checkout -b feature/add-load-balancer - Work on the branch: Perform your changes and commits.
- Push the branch:
git push origin feature/add-load-balancer - Merge via Pull Request: Use your Git provider (GitHub/GitLab) to create a Pull Request (PR). This allows your teammates to review your infrastructure code before it is merged into the main line of code.
Managing Branches
git branch: List all branches.git checkout main: Switch back to the main branch.git merge feature/add-load-balancer: Incorporate the changes from your feature branch into the current branch.
Advanced Git for Automation: Rebase and Reset
Sometimes, your local history gets messy. Perhaps you committed several times while debugging a script, and you want to clean that history up before merging it into the production codebase.
Using Interactive Rebase
Interactive rebase allows you to rewrite commit history—you can squash multiple small commits into one, rename them, or delete them.
# Rebase the last 3 commits
git rebase -i HEAD~3
In the editor that opens, you can change pick to squash for the commits you want to merge into the previous one. This creates a clean, readable project history that is much easier to audit later.
Rolling Back Changes
If you accidentally make a change that breaks your provisioning script, you need to know how to undo it.
- To discard local changes in a file:
git checkout -- filename - To undo a commit but keep the changes staged:
git reset --soft HEAD~1 - To completely remove a commit and its changes:
git reset --hard HEAD~1
Note: Be extremely careful with
git reset --hard. It will permanently delete any uncommitted work in your directory. Always ensure you have a backup or that you truly want to discard those changes before running this command.
Integrating Git with Automation Tools
Git does not exist in a vacuum. In a professional environment, Git is the trigger for your CI/CD (Continuous Integration/Continuous Deployment) pipeline.
The CI/CD Trigger Mechanism
Most modern automation platforms (like Jenkins, GitHub Actions, or GitLab CI) are configured to watch your Git repository. As soon as you push a commit to the main branch, the CI/CD server detects the change, pulls the latest code, and executes your provisioning scripts (e.g., terraform apply or ansible-playbook).
Example: GitHub Actions Workflow
Create a file at .github/workflows/deploy.yaml to automate your infrastructure updates:
name: Deploy Infrastructure
on:
push:
branches:
- main
jobs:
provision:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Terraform
run: |
terraform init
terraform apply -auto-approve
This simple file ensures that your infrastructure is always in sync with your Git repository. If someone changes a setting in main.tf, the server automatically applies it.
Best Practices for Automation Repositories
To maintain high-quality automation code, you must treat your infrastructure scripts with the same rigor as application source code.
1. Write Meaningful Commit Messages
A commit message like "update" or "fix" is useless for future troubleshooting. Use the imperative mood: "Add load balancer security group," or "Update database instance size to t3.medium."
2. Use .gitignore Files
Never commit secrets or temporary files. Create a .gitignore file in your repository root to ignore sensitive data.
# Example .gitignore
.terraform/
*.tfstate
*.tfstate.backup
.env
secret_keys.pem
3. Peer Review is Mandatory
Never push directly to main. Always use Pull Requests. This ensures that at least one other person has looked at your infrastructure changes to verify they won't accidentally delete a production database or open an insecure port.
4. Keep Commits Atomic
Each commit should do one thing. If you are updating both the network configuration and the application server configuration, split them into two separate commits. This makes it much easier to revert just one part of the change if something goes wrong.
Comparison of Version Control Strategies
When working in a team, you need a strategy to manage how code flows from development to production.
| Strategy | Pros | Cons | Best For |
|---|---|---|---|
| GitFlow | Strict, clear structure, great for releases | Complex, overhead for small teams | Large, enterprise-scale projects |
| GitHub Flow | Fast, simple, encourages frequent deployment | Can get messy without discipline | Small teams, continuous delivery |
| Trunk-Based | Extremely fast, prevents integration hell | Requires high automation maturity | Teams with high test coverage |
Callout: Why "Infrastructure as Code" (IaC) Needs Git Without Git, IaC is just a collection of scripts. With Git, IaC becomes an auditable, versioned, and reversible process. If your infrastructure fails, you can use
git revertto roll back your entire data center configuration to a known-good state in minutes.
Common Mistakes and How to Avoid Them
Even experienced engineers trip over Git. Here are the most common pitfalls and how to avoid them.
1. Committing Sensitive Information
The Mistake: Accidentally committing an AWS access key or a database password.
The Fix: If you do this, you must rotate the credentials immediately. Then, use a tool like git-filter-repo to scrub the file from your history. Prevention is key: always use a .gitignore file and never store secrets in plain text.
2. The "Merge Conflict" Nightmare
The Mistake: Two people edit the same line of the same file simultaneously.
The Fix: Communicate with your team. Pull frequently using git pull to ensure your local repository is up to date with the remote server. If a conflict occurs, Git will mark the file; you must manually edit the file to resolve the conflict and then commit the resolution.
3. Working on the Wrong Branch
The Mistake: You make significant changes, only to realize you are on main instead of your feature branch.
The Fix: Use git stash to save your work, switch branches, and then git stash pop to bring your changes to the correct branch.
git stash
git checkout -b new-feature
git stash pop
4. Ignoring Documentation
The Mistake: Assuming your code is self-documenting.
The Fix: Always include a README.md file in your repository explaining how to initialize the environment, what the scripts do, and how to run the deployment. This is vital for onboarding new team members.
Security in Version Control
In the context of deployment and automation, your Git repository is a high-value target. If an attacker gains access to your infrastructure repository, they essentially own your production environment.
Securing Your Repository
- Access Control: Use the Principle of Least Privilege. Not everyone needs write access to the production branch.
- Signed Commits: Use GPG keys to sign your commits. This proves that the code came from you and hasn't been tampered with.
- Branch Protection: In platforms like GitHub/GitLab, enable "Branch Protection Rules." This prevents anyone from pushing directly to
mainand requires PR approval before merging. - Secret Scanning: Use automated tools (like
gitleaksor built-in repository scanners) to detect if someone accidentally pushes a secret to the repo.
Maintaining a Clean History
A long-term automation project can quickly become filled with hundreds of "typo fix" commits that obscure the actual changes. Maintaining a clean history is not about vanity; it is about making it possible to use git bisect to find exactly when a bug was introduced.
The Power of git bisect
git bisect is a powerful tool that uses binary search to find the commit that introduced a bug. If you have a clean history, you can identify the culprit in seconds.
git bisect startgit bisect bad(the current state is broken)git bisect good <commit-hash>(the last known good state)- Git will then check out the middle commit, and you tell it whether it is good or bad. It repeats this until the exact commit is found.
This is why atomic commits and descriptive messages are so important. If your commit messages are clear, you can often identify the problem just by reading the history without even running the bisect tool.
Summary Checklist for Automation Engineers
To ensure you are using Git effectively in your daily work, use this checklist before you push your code:
- Status Check: Did I run
git statusto ensure no unexpected files are being added? - Secret Check: Did I double-check that no
.envor.pemfiles are in the staging area? - Branch Check: Am I on a feature branch, and not
main? - Commit Message: Is the message descriptive and in the imperative mood?
- Peer Review: Have I requested a review from a teammate for these infrastructure changes?
- Documentation: Did I update the
README.mdif I changed the provisioning process?
Conclusion: Key Takeaways
Version control is the backbone of reliable infrastructure and automation. By mastering the concepts outlined in this lesson, you move from being a "scripter" to a professional automation engineer who builds predictable, auditable, and secure systems.
Key Takeaways:
- Git is Distributed: Leverage the distributed nature of Git to maintain a robust, local history of your infrastructure, protecting you from server-side failures.
- The Three States Matter: Always track your files through the Modified, Staged, and Committed states to ensure your repository history is clean and atomic.
- Branching is Safety: Never work directly on the production branch. Use feature branches and Pull Requests to ensure every infrastructure change is reviewed and tested before being applied to the environment.
- Automation Integration: Connect your Git repository to your CI/CD pipelines to create a "push-to-deploy" workflow that ensures your infrastructure is always in the state you intended.
- Security First: Treat your infrastructure code as a high-security asset. Use branch protection rules, sign your commits, and never store secrets in your repository.
- Clean History is Maintainable History: Use tools like rebase to squash unnecessary commits, and keep your history readable so that tools like
git bisectcan help you troubleshoot issues quickly. - Culture of Documentation: Git is only as good as the information within it. Use clear commit messages and maintain an up-to-date
README.mdto ensure that your infrastructure is understandable to the rest of your team.
By following these principles, you will minimize configuration drift, reduce the risk of deployment-related outages, and build a culture of accountability within your engineering team. Git is not just a tool; it is a way of working that ensures the software and infrastructure you build can stand the test of time.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons