Introduction
Git is a version control system. In simple terms, it keeps a complete history of every change you make to your code. Every time you "save" (we say commit), git takes a snapshot of the state of all your files at that moment. You can go back to any snapshot at any time.
Why it's essential:
- Safety: your code is saved on a remote server. If your hard drive dies, if you run a bad
rm -rf, your code is safe. - History: you can see exactly what you changed, when, and why. If a change breaks something, you roll back.
- Collaboration: multiple people can work on the same project in parallel. Git handles merging changes.
- Traceability: at 42, the Moulinette checks that your code is properly pushed to the Vogsphere. No push, no correction. Git is mandatory.
Git was created in 2005 by Linus Torvalds (the creator of Linux) because he needed a fast and reliable tool to manage the Linux kernel's code, which has millions of lines and thousands of contributors.
Git is distributed
Most people picture a centralized system: a single server that stores the code, and everyone connects to it. Git doesn't work like that.
With git, every person has a complete copy of the project, including the full history. You can work, commit, create branches, roll back -- all of that without an internet connection, locally on your machine.
The remote server (GitHub, GitLab, 42's Vogsphere) is just a synchronization point. You send your changes when you're ready, and you pull others' changes. But the server isn't needed to work -- it's needed to share.
+----------------+ git push +----------------+ | Your machine | ---------------> | Server | | (local) | | (remote) | | | <--------------- | | | complete | git pull | complete | | copy | | copy | +----------------+ +----------------+
The three zones of git
Git organizes your work into three zones. Understanding these three zones is understanding git:
Working directory --git add--> Staging area --git commit--> Repository
(your files) (index) (history)
| | |
You edit here You choose here Commits live hereThis three-step system might seem complicated at first, but it gives you total control. You can modify 10 files but only commit 3. You can check exactly what's going to be committed before doing it.
Configuring git
Identity
Before you can commit, git needs to know who you are. Every commit carries a name and email -- that's what shows up in the history.
A flag (or option) is a parameter that starts with - or -- and modifies a command's behavior. The --global flag applies the configuration to your entire system (all your projects). Without --global, the configuration only applies to the current project.
To verify:
Default editor
Some git commands open a text editor (to write a commit message, for example). The default is often vim. If you prefer nano:
Where is the config stored?
--global->~/.gitconfig- Without flag ->
.git/configin the project
Creating a repository
Two ways to get started:
git init -- Create a new repository
git clone -- Copy an existing repository
The difference between clone and simply copying a folder: clone automatically establishes the connection to the remote server (the "remote"). You'll be able to git push and git pull without additional configuration.
The basic cycle: status, add, commit, push
This is the workflow you'll repeat hundreds of times:
1. You modify your files
2. git status -> you check what changed
3. git add -> you stage files for the commit
4. git commit -> you create a snapshot
5. git push -> you send to the servergit status -- Where do I stand?
After modifying a tracked file:
After git add:
After git commit:
Make a habit of running git status before every add and before every commit. It's your GPS.
git add -- Stage files
The . means "everything in the current directory and its subdirectories". It's convenient but dangerous -- you might add files you didn't want (compiled files, temporary files). Always run git status first to check.
The file stays modified but is no longer staged.
git commit -- Create a snapshot
The -m flag lets you write the message directly. Without -m, git opens a text editor for you to write the message.
- Describes what you did, not what you're going to do
- Is short and specific (one line, ideally 50 characters max)
- Starts with an action verb: "add", "fix", "update", "remove"
Good messages:
add ft_putchar function
fix segfault in ft_split with empty string
update Makefile to include bonus rule
remove unused variable in ft_strlenBad messages:
update <- too vague, update what?
fix <- fix what?
wip <- nobody will know what you were doing
asdfgh <- seriously
done <- done with what?git push -- Send to the server
After the push, your code is safe on the server. Others (and the Moulinette) can access it.
This means the server has commits you don't have. You need to git pull first to fetch the changes, then push again.
git pull -- Fetch from the server
- Downloads new commits from the server
- Merges the server's changes with yours
If you're working alone, it happens automatically without conflicts. In a team, it's different -- but branches and conflict resolution are more advanced topics.
Viewing the history
git log -- The commit history
Each commit shows:
- The unique identifier: a long string of letters and numbers (40 characters). It's the commit's serial number -- no other commit will ever have the same one.
- HEAD -> master: indicates this is the most recent commit on the master branch.
- The author and date.
- The message.
One commit per line, with the short hash (7 characters) and the message.
git diff -- View changes
Lines with + are added (green in the terminal). Lines with - are removed (red). Lines without a sign are context.
Ignoring files -- .gitignore
Some files should never be versioned:
- Compiled files (
.o,.a,a.out) -- they're regenerated at each compilation - Editor temporary files (
.swp,~) - OS-specific files (
.DS_Storeon macOS) - Files containing secrets (API keys, passwords)
The .gitignore file at the project root lists the patterns to ignore:
Once in the .gitignore, files no longer appear in git status and are no longer added by git add ..
Typical .gitignore at 42
# Compiled files
*.o
*.a
*.so
*.dylib
a.out
# Editor files
*~
*.swp
.vscode/
.idea/
# OS files
.DS_Store
Thumbs.db
# Debug
*.dSYM/Put this .gitignore in every project from the very first commit. It's a good habit.
The SSH key
Why SSH?
To communicate with a git server (GitHub, Vogsphere), you need to prove your identity. Two options:
- HTTPS: you provide your login + password on every push. Convenient but tedious.
- SSH: you set up a key pair once, and then authentication is automatic.
At 42 we use SSH.
How it works
SSH uses a system of two linked keys: a private key (that you keep secret) and a public key (that you give to the server). It's like a mailbox: anyone can drop in mail (public key = the slot), but only you can open it (private key = the box key). The server verifies you're the owner of the public key by asking a challenge that only someone with the private key can solve.
- The private key stays on your machine, in
~/.ssh/. Never share it ever. It's the equivalent of your password. - The public key is given to the server (GitHub, Vogsphere). It allows the server to verify it's really you.
Generate an SSH key
-t ed25519: ed25519 is the recommended key type. It's the most recent and most secure. If it doesn't work on your system, use-t rsa -b 4096instead.-C: a comment to identify the key (convention: your email).- Passphrase: a password that protects your private key. You can leave it empty for convenience, but it's less secure.
Two files are created:
~/.ssh/id_ed25519-- the private key (NEVER share it)~/.ssh/id_ed25519.pub-- the public key (this is the one you give out)
Add the key to the server
Copy everything (from ssh-ed25519 to the end).
This message means it works. The "does not provide shell access" is normal -- GitHub is not a shell server, it's a git server.
Key permissions
The private key must have 600 permissions (only you can read it). Otherwise SSH refuses to use it:
If you see the error "UNPROTECTED PRIVATE KEY FILE", the permissions are too open.
ssh-agent -- Avoid retyping the passphrase
If you set a passphrase on your key, SSH asks for it every time. To avoid that:
The SSH agent remembers your passphrase until you close the terminal.
Undoing mistakes
Undo changes to a file (before add)
The file goes back to its state at the last commit. Warning: uncommitted changes are lost permanently.
Undo an add (unstage)
The file leaves the staging area but your changes are preserved.
Modify the last commit
You forgot a file, or you want to fix the message:
Go back to a previous commit (to look around)
You're in "detached HEAD" mode. You can look at the code at that point in history. To come back to the present:
git reset -- Go back in time (with or without loss)
Useful commands
git show -- View a commit's contents
Shows the message and changes of the commit.
git blame -- Who wrote this line?
For each line: which commit introduced it, by whom, and when. Useful for understanding a file's history.
git stash -- Temporarily set aside changes
You have changes in progress but need to switch context (a hotfix, another exercise):
It's like a stack of drafts.
Best practices
The daily cycle
The git workflow you'll repeat every day:
- Code / modify your files
git statusto check what changedgit addto stage the filesgit commit -m "clear message"to savegit pushto send to the server
Commit often, in small logical increments. One commit per feature or fix. Not one giant commit with 10 different changes.
Before submitting a project
Checklist:
git status-- is everything committed? Nothing in red?git log-- does the last commit have the right content?git push-- is everything pushed?- Check on the web interface that the correct commit is visible
- Read the subject one last time to make sure you haven't forgotten anything
Quiz
Test your knowledge — select the correct answer for each question
git add and git commit?git status and see a file in red under "Changes not staged for commit". What does that mean?a.out and you now add it to .gitignore. What happens?git add (removes a file from the staging area) without losing changes?.git/ folder contain?git push and get the error "rejected (non-fast-forward)". Why?git clone and git init?~/.ssh/id_ed25519) have 600 permissions?