Support Free C++ Education
Help us create more high-quality C++ learning content. Your support enables us to build more interactive projects, write comprehensive tutorials, and keep all content free for everyone.
From Theory to Practice
You've learned what version control is and installed Git. Now it's time to get hands-on.
This article walks through the core Git workflow step by step. By the end, you'll have created a repository, tracked files, and made commits. These operations form the foundation of everything else in Git.
Creating a Project
Let's start with a simple C++ project. Open your terminal and create a new folder:
mkdir cpp-calculator
cd cpp-calculator
Create a basic C++ file. You can use any text editor, or create it from the terminal:
# On macOS/Linux
touch main.cpp
# On Windows (in Git Bash)
touch main.cpp
Open main.cpp in your editor and add this code:
#include <iostream>
int main() {
std::cout << "Calculator v0.1\n";
return 0;
}
Save the file. You now have a simple project ready for version control.
Initializing a Repository
Turn this folder into a Git repository:
git init
You'll see:
Initialized empty Git repository in /path/to/cpp-calculator/.git/
That's it. The folder is now a Git repository. Git created a hidden .git directory that stores all version control data.
What happened:
- Git created the
.gitfolder - No files are tracked yet (Git doesn't automatically track existing files)
- You're on a branch called
main(but there are no commits yet)
Checking Status
The git status command shows the current state of your repository:
git status
Output:
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
main.cpp
nothing added to commit but untracked files present (use "git add" to track)
Reading this output:
- "On branch main": You're on the main branch
- "No commits yet": No snapshots have been saved
- "Untracked files": Git sees
main.cppbut isn't tracking it - Git helpfully suggests what to do next
git status is your most-used command. Run it constantly to understand what's happening.
The Three Areas
Before going further, understand Git's three main areas:
Working Directory: Where you edit files. This is your normal folder with your project files.
Staging Area (also called "Index"): A preparation area for your next commit. Files here are marked "ready to commit."
Repository: The permanent history. Each commit is a snapshot stored here.
The workflow is:
Working Directory → Staging Area → Repository
(edit) (stage) (commit)
This two-step process (stage, then commit) seems like extra work, but it gives you precise control over what goes into each commit.
Adding Files
To track a file, add it to the staging area:
git add main.cpp
No output means success. Check status again:
git status
Output:
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: main.cpp
What changed:
main.cppmoved from "Untracked files" to "Changes to be committed"- The file is now "staged," ready to be committed
- Git shows it as "new file" since this is the first time it's being tracked
Making Your First Commit
Create a commit to save this snapshot:
git commit -m "Add initial calculator program"
Output:
[main (root-commit) a1b2c3d] Add initial calculator program
1 file changed, 6 insertions(+)
create mode 100644 main.cpp
Reading this output:
main: The branch nameroot-commit: This is the first commit in the repositorya1b2c3d: The commit's unique identifier (hash), shortened1 file changed, 6 insertions(+): What changed
Check status:
git status
On branch main
nothing to commit, working tree clean
"Working tree clean" means your working directory matches the last commit. All changes are saved.
The -m Flag
The -m flag lets you write the commit message inline:
git commit -m "Your message here"
Without -m, Git opens your configured editor for you to write a longer message. For simple commits, -m is convenient. For complex changes, write detailed messages in the editor.
Making Changes
Let's modify our code. Update main.cpp:
#include <iostream>
int add(int a, int b) {
return a + b;
}
int main() {
std::cout << "Calculator v0.2\n";
std::cout << "5 + 3 = " << add(5, 3) << "\n";
return 0;
}
Check status:
git status
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: main.cpp
no changes added to commit (use "git add" and/or "git commit -a")
Git sees the file changed but the changes aren't staged. Notice the helpful hints about what you can do.
Viewing Changes
See exactly what changed with git diff:
git diff
Output shows lines added (green +) and removed (red -):
@@ -1,6 +1,12 @@
#include <iostream>
+int add(int a, int b) {
+ return a + b;
+}
+
int main() {
- std::cout << "Calculator v0.1\n";
+ std::cout << "Calculator v0.2\n";
+ std::cout << "5 + 3 = " << add(5, 3) << "\n";
return 0;
}
git diff shows unstaged changes (differences between working directory and staging area).
Stage and Commit the Changes
git add main.cpp
git commit -m "Add addition function"
[main b2c3d4e] Add addition function
1 file changed, 6 insertions(+), 1 deletion(-)
You now have two commits in your history.
Viewing History
See your commit history:
git log
commit b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u (HEAD -> main)
Author: Your Name <your.email@example.com>
Date: Mon Jan 15 14:30:00 2024 -0500
Add addition function
commit a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
Author: Your Name <your.email@example.com>
Date: Mon Jan 15 14:15:00 2024 -0500
Add initial calculator program
Each commit shows:
- Full hash (unique identifier)
- Author and email
- Date and time
- Commit message
For a compact view:
git log --oneline
b2c3d4e Add addition function
a1b2c3d Add initial calculator program
Adding Multiple Files
Let's expand our project. Create a header file:
// calculator.h
#pragma once
int add(int a, int b);
int subtract(int a, int b);
Create an implementation file:
// calculator.cpp
#include "calculator.h"
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
Update main.cpp:
#include <iostream>
#include "calculator.h"
int main() {
std::cout << "Calculator v0.3\n";
std::cout << "5 + 3 = " << add(5, 3) << "\n";
std::cout << "5 - 3 = " << subtract(5, 3) << "\n";
return 0;
}
Check status:
git status
On branch main
Changes not staged for commit:
modified: main.cpp
Untracked files:
calculator.cpp
calculator.h
You can add files one at a time, or add multiple at once:
# Add specific files
git add main.cpp calculator.h calculator.cpp
# Or add all changes
git add .
The . means "current directory and everything in it." Use it carefully; it stages everything.
git commit -m "Refactor into separate header and implementation"
Ignoring Files
C++ projects generate files you don't want to track: compiled binaries, object files, IDE settings. Tell Git to ignore them with a .gitignore file.
Create .gitignore:
# Compiled objects
*.o
*.obj
# Compiled executables
*.exe
*.out
calculator
# IDE files
.vscode/
.idea/
*.swp
# Build directories
build/
cmake-build-*/
# Operating system files
.DS_Store
Thumbs.db
Add and commit the .gitignore:
git add .gitignore
git commit -m "Add gitignore for C++ project"
Now if you compile your code, the generated files won't appear as "untracked."
The Complete Workflow
You now know the basic Git workflow:
# 1. Make changes to files
# 2. See what changed
git status
git diff
# 3. Stage changes
git add <files>
# 4. Commit changes
git commit -m "Descriptive message"
# 5. View history
git log
Repeat this cycle as you develop. Each commit captures a meaningful milestone in your project.
Practice Exercises
Reinforce what you've learned:
Exercise 1: Add a multiplication function to the calculator. Create a commit with the changes.
Exercise 2: Add a division function (handle division by zero gracefully). Make it a separate commit from multiplication.
Exercise 3: Run git log --oneline to see your commit history. Notice how each commit represents a distinct change.
Exercise 4: Make a change, run git diff to see it, then run git checkout -- <filename> to discard it. (This undoes uncommitted changes, be careful!)
Common Mistakes and Solutions
Committed Too Soon
Made a commit with a typo or mistake? If you haven't pushed anywhere:
# Amend the last commit
git commit --amend -m "Better message"
This replaces the last commit with a new one.
Added Wrong File
Staged a file you didn't mean to?
# Unstage a specific file
git restore --staged <filename>
# Unstage everything
git restore --staged .
Want to See What's Staged
git diff shows unstaged changes. To see staged changes:
git diff --staged
Forgot What Changed in a Commit
See what a specific commit changed:
git show <commit-hash>
What's Next
You can now track projects with Git. The next step is understanding commits more deeply: what they contain, how to navigate them, and how to undo mistakes.
Next article: Understanding Commits - Deep dive into what commits really are and how to work with history.
Keep practicing the basic workflow until it becomes automatic. Create test projects, make changes, commit frequently. The muscle memory will serve you well.
Part of the Git Fundamentals series.
Support Free C++ Education
Help us create more high-quality C++ learning content. Your support enables us to build more interactive projects, write comprehensive tutorials, and keep all content free for everyone.
About the Author
Software engineer and C++ educator passionate about making programming accessible to beginners. With years of experience in software development and teaching, Imran creates practical, hands-on lessons that help students master C++ fundamentals.
Related Articles
Working with GitHub: Remote Repositories and Collaboration
Connect your local Git repository to GitHub. Learn to push, pull, clone, and collaborate with remote...
Git Branches and Merging: Parallel Development Without Chaos
Learn to use Git branches for safe experimentation and parallel development. Create branches, merge...
Understanding Git Commits: Snapshots, History, and Time Travel
Go beyond basic commits. Learn what commits really are, how to write meaningful commit messages, nav...
Article Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!