Git Fundamentals
January 16, 2025
Master version control with Git-- from basic commits and pushes to merge conflicts, rebasing, and branching strategies used in professional cloud engineering teams.
Git Fundamentals
Git was invented by Linus Torvalds in 2005 to manage the Linux kernel development process. Since then, it has become the most popular version control system in the world, used by millions of developers and organizations. Multiple platforms use some form of git (github, gitlab, bitbucket, etc.), with github being the most popular.
Version control is essential for modern software development and infrastructure management. It doesn't matter what you're working on, being able to track changes and collaborate with others is critical. This guide covers the Git fundamentals you need to work effectively in professional cloud engineering environments. You'll learn core concepts, essential commands, branching strategies, and how to handle common Git workflows and problems.
Why Cloud Engineers Need Git
Git is for anyone working on code. This can be software, infrastructure as code, even documentation. Keep a working history of your files, just in case you need to track changes or revert to an earlier version.
- Track infrastructure as code: Terraform modules, Ansible playbooks, CloudFormation templates, and Helm charts.
- Collaborate on projects: Work with team members on shared codebases without overwriting each other's changes. If a conflict arises, it's better to fix the merge conflict than overwrite someone else's code without realizing.
- Review changes before deployment: Use pull requests and code reviews to catch errors before they reach production.
- Rollback mistakes: If a deployment breaks, revert to a previous working state in seconds.
- Automate deployments: Push and pull requests can trigger CI/CD pipelines when code is pushed to specific branches.
- Audit changes: See who changed what, when, and why. This is critical for compliance and troubleshooting.
Core Git Concepts
Repositories
A repository (repo) is a project tracked by Git. It contains:
- All your files (code, configs, docs)
- A hidden
.git
directory storing the full history of changes - Metadata about commits, branches, and remote connections
Repos can be local (on your machine) or remote (on GitHub, GitLab, Bitbucket). You son't have to store your code on a remote, git is fully functional on your local machine.
Commits
A commit is a snapshot of your project at a specific point in time. Each commit has:
- A unique ID (SHA hash like
a3f4b2c
) - An author and timestamp
- A commit message describing the change
- A pointer to the previous commit (forming a history chain)
Good commit messages are short but descriptive:
**Good**:
- Add VPC configuration for staging environment
- Fix S3 bucket policy to allow CloudFront access
- Update node scaling thresholds
**Bad**:
- update
- fix bug
- changes
- try1
- try2
- idk
Branches
A branch is an independent line of development. The default branch used to be master
, now it's commonly main
. You create branches to:
- Work on features without affecting production code
- Test changes in isolation
- Collaborate on separate tasks simultaneously
Common branching patterns:
main
ormaster
: Production-ready codedev
ordevelop
: Integration branch for ongoing workfeature/<feature name>
: New feature branchhotfix/<hotfix name>
: Urgent production fix- Sometimes
release/<release name>
: for when only specific changes are needed for a release
Merging
Merging combines changes from one branch into another. For example:
- Create a feature branch:
git checkout -b feature/new-vpc
- Make changes and commit
- Merge back into
main
:git checkout main && git merge feature/new-vpc
If there are changes to the same lines of code on both branches, you'll get a merge conflict that must be resolved manually.
Remote Repositories
Remotes are versions of your repo hosted on a server (GitHub, GitLab, Bitbucket). Common commands:
git clone <url>
: Copy a remote repo to your local machinegit fetch
: Download remote changes without merginggit pull
: Download and merge remote changesgit push
: Upload local commits to a remote repo
Essential Git Commands
Setting Up Git
# Configure your name and email (appears in commits)
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
# Check your configuration
git config --list
# Set default branch name to 'main'
git config --global init.defaultBranch main
# Set default editor (optional)
git config --global core.editor "nano"
Creating and Cloning Repositories
# Create a new Git repo in current directory
git init
# Clone an existing repo
git clone https://github.com/username/repo.git
# Clone into a specific folder
git clone https://github.com/username/repo.git my-folder
Making Changes
Most modern IDEs (VSCode, PyCharm, etc.) have built-in Git support. You can stage and commit changes directly from your editor. At first, it can be easier to just point and click, but it's beneficial to learn what you're doing by typing the commands when you're getting started.
# Check status (shows modified, staged, untracked files)
git status
# Stage a file for commit
git add filename.txt
# Stage all changes
git add .
# Commit staged changes
git commit -m "Add Terraform config for VPC"
# Stage and commit in one step (for tracked files only)
git commit -am "Update security group rules"
# View commit history
git log
git log --oneline # compact view
git log --graph --oneline --all # visual branch history
git log --oneline
is a great way to find a specific commit by its hash. If you want to revert to an earlier version, finding that commit's hash is the first step.
Viewing Changes
# Show unstaged changes
git diff
# Show staged changes
git diff --staged
# Show changes in a specific commit
git show a3f4b2c
# Compare two branches
git diff main feature/new-vpc
Branching and Merging
# List all branches
git branch
# Create a new branch
git branch feature/monitoring
# Switch to a branch
git checkout feature/monitoring
# Create and switch in one command
git checkout -b feature/logging
# Merge a branch into current branch
git merge feature/monitoring
# Delete a branch
git branch -d feature/monitoring
Undoing Changes
# Discard unstaged changes to a file
git checkout -- filename.txt
# Unstage a file (keep changes)
git reset HEAD filename.txt
# Undo last commit (keep changes staged)
git reset --soft HEAD~1
# Undo last commit (discard changes)
git reset --hard HEAD~1
# Revert a commit (creates a new commit that undoes changes)
git revert a3f4b2c
If you want to reset to a specific commit, you can use git reset --hard <commit hash>
. From there, you can git push -f
to force push the changes to the remote repository and overwrite the newer commits.
Git Workflows for Cloud Engineering
Feature Branch Workflow
This is a sample workflow to create an "add monitoring" branch.
- Start from
main
:git checkout main && git pull
- Create a feature branch:
git checkout -b feature/add-monitoring
. There are multiple ways to accomplish this,git checkout -b
,git switch -c
, andgit branch -c
all create a new branch. - Make changes and commit:
git add . && git commit -m "Add Prometheus config"
- Push to remote:
git push -u origin feature/add-monitoring
- Open a pull request (PR) on GitHub/GitLab
- After review, merge into
main
- Delete the feature branch:
git branch -d feature/add-monitoring
GitFlow Workflow
More structured, common in larger teams:
main
: Production codedevelop
: Integration branchfeature/*
: New features (branch offdevelop
, merge back intodevelop
)release/*
: Prepare for production releasehotfix/*
: Urgent production fixes (branch offmain
, merge back intomain
anddevelop
)
Trunk-Based Development
Simplified workflow for fast-moving teams:
- Everyone commits to
main
frequently (multiple times per day) - Feature flags control incomplete features
- CI/CD runs on every commit
- Minimal long-lived branches
Handling Merge Conflicts
Conflicts happen when two branches modify the same lines. Git marks conflicts in the file:
<<<<<<< HEAD
resource "aws_instance" "web" {
instance_type = "t3.medium"
=======
resource "aws_instance" "web" {
instance_type = "t3.large"
>>>>>>> feature/update-instance-type
To resolve:
- Open the file in an editor
- Choose which change to keep (or combine them)
- Remove conflict markers (
<<<<<<<
,=======
,>>>>>>>
) - Stage the file:
git add filename.tf
- Commit the resolution:
git commit -m "Resolve instance type conflict"
Use a merge tool for complex conflicts:
git mergetool
Best Practices for Cloud Engineering
Commit Small, Logical Changes
Each commit should represent a single logical change. Avoid:
- Mixing unrelated changes in one commit
- Committing broken code
- Giant commits with 50+ file changes
Use .gitignore
Exclude files that shouldn't be tracked:
# .gitignore example
*.tfstate
*.tfstate.backup
.terraform/
*.pem
*.key
.env
node_modules/
__pycache__/
*.log
Never Commit Secrets
Never commit:
- API keys
- Passwords
- Private keys
- Access tokens
Use environment variables, secret managers (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault), or .env
files (add to .gitignore
). Keep in mind that if you have a .env file with your sensitive values, you will NOT have access to it when you push to GitHub or clone to a new workspace. Every single workspace will need access to the secrets.
If you accidentally commit a secret:
- Immediately rotate the credential
- Remove it from Git history (use
git filter-branch
or BFG Repo-Cleaner) - Force-push to remote (NOTE: disrupts team)
Review Changes Before Committing
# Always check what you're about to commit
git status
git diff
# Stage carefully
git add -p # interactively stage changes
Pull Before You Push
Always pull remote changes before pushing to avoid conflicts:
git pull origin main
# Resolve any conflicts
git push origin main
Use Tags for Releases
Tag production releases for easy reference:
git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin v1.2.0
Integrating Git with Cloud Workflows
Infrastructure as Code
Store Terraform, CloudFormation, or Pulumi configs in Git:
infrastructure/
├── environments/
│ ├── prod/
│ ├── staging/
│ └── dev/
├── modules/
│ ├── vpc/
│ ├── eks/
│ └── rds/
└── README.md
CI/CD Pipelines
Trigger deployments on Git events:
- Push or merge to
main
-> deploy to production - Push or merge to
develop
-> deploy to staging - Open PR -> run tests and linting
Example GitHub Actions workflow:
name: Deploy to AWS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
- name: Deploy with Terraform
run: |
terraform init
terraform apply -auto-approve
GitOps
Entire system state defined in Git. Tools like ArgoCD or Flux continuously sync Git with Kubernetes clusters. Changes to Git automatically update production.
Common Git Problems and Solutions
Problem: "I committed to the wrong branch"
# Move last commit to another branch
git branch feature/my-feature # create branch at current commit
git reset --hard HEAD~1 # undo commit on current branch
git checkout feature/my-feature # switch to new branch
Problem: "I need to undo a pushed commit"
# Revert creates a new commit that undoes changes
git revert a3f4b2c
git push origin main
Problem: "My branch is behind remote"
# Fetch remote changes
git fetch
# Merge remote changes
git pull origin main
# Or rebase (cleaner history but rewrites commits)
git pull --rebase origin main
Problem: "I want to discard all local changes"
# Discard all unstaged changes
git checkout -- .
# Reset to match remote
git fetch origin
git reset --hard origin/main
Problem: "I accidentally committed a large file"
# Remove from last commit
git rm --cached large-file.zip
git commit --amend -m "Remove large file"
git push --force
Learning Path: From Basics to Mastery
- First: Set up Git, create a repo, make commits. Practice
add
,commit
,status
,log
. - Second: Learn branching. Create feature branches, merge them, resolve a simple conflict.
- Third: Connect to GitHub/GitLab. Clone, push, pull, and open a pull request.
- Fourth: Practice real workflows. Manage a Terraform project with Git, simulate team collaboration.
- Fifth: Learn advanced commands:
rebase
,cherry-pick
,stash
,reflog
.
Another good way to start is find a small public repo, clone it locally, and practice the commands on it. You can find some here: https://github.com/trending
Practical Exercises
- Initialize a repo: Create a Git repo for a Terraform project. Make commits for VPC, subnets, and security groups.
- Branching practice: Create a feature branch, make changes, merge into
main
, and resolve a conflict. - Collaborate on GitHub: Fork a public repo, make changes, open a pull request.
- Simulate a rollback: Make a breaking change, commit, push, then use
git revert
to undo it. - Set up CI/CD: Create a GitHub Actions workflow that runs
terraform validate
on every push.
This needs to become routine. Some skills are "nice to have", this is an absolute "must have".
The Bottom Line: Git Is Essential
Every professional cloud engineer uses Git. Things break all the time, and when that happens, you need to be able to fix it. That's what we use Git for. If you're working on a team that's pushing changes, you need to understand Git in order to be a basic member of the team. You can't just make your code changes, push them, and hope for the best. Use a proper branching strategy and make sure you're not overwriting other people's code.
For more cloud engineering guidance, check out what does a cloud engineer do and how to get a cloud engineering job with no experience.