Version Control with Git¶
Version Control¶
What Is Version Control?¶
Version control lets us manage software development safely:
Track changes
Look at older revisions
Revert to earlier revisions
Share code/collaborate easily
Easily go back to a previously working version if you break something
You may have used “homemade version control” like this:
resume-version-1.docx
resume-version-2.docx
resume-version-2FINAL.docx
resume-version-2NEWFINAL.docx
resume-version-2UPDATENEWFINAL.docx
Git is like this — but a million times better
Multiple Files¶
Tracks entire project (could be many files in folders, even):
$ ls
NOTES app_setup.py db_reset.py search.py
README config.py flask/ tests.db
app/ db_create.py requirements.txt tests.py
Git Intro¶
Git¶
Most popular Open Source version control program
Runs on Linux, OSX, and Windows
Main concern: safety!
Terminology¶
- Directory
Folder of files (which can contain subdirectories).
- Repository
Project kept under version control; can contain subdirectories.
- Working Copy
Your particular copy of a repository.
Until we turn a directory into a repository, git won’t work
(and isn’t tracking anything):
$ mkdir play $ cd play $ git status fatal: Not a git repository (or any of the parent directories): .git
Configuring Git¶
Git wants to know who you are so it can identify the commits by user
Two commands (one for email, one for name):
$ git config --global user.email "balloonicorn@hackbrightacademy.com" $ git config --global user.name "Balloonicorn Jones"
Do this as soon as possible so your code is attributed to you correctly
You only need to do this one time
Creating Repository¶
Turn your directory into a repository with git init.
$ git init
Initialized empty Git repository in /home/user/src/play/.git/
You only need to do this once.
You can do it when you create the project or at a later point.
What does git init do?
git init will create a directory called .git/ wherever you run the command. So, a Git repository is really just any directory that contains a valid .git/ folder. As long as your project already has a .git/ directory, you’ll never need to run git init again.
Untracked Files¶
Let’s create a file, hello.py, in our repository
print('Hello')
Git can tell we’ve created this file and that it’s untracked
$ git status On branch main Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) hello.py nothing added to commit but untracked files present (use "git add" to track)
Tracking a File¶
For Git to manage files, “track” them with git add:
$ git add hello.py
Once we do that, we can see that Git is tracking our file:
$ git status On branch main Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: hello.py
First Check-In!¶
Our program is working! Let’s “commit” it:
$ git commit -a -m "Say hello"
[main (root-commit) 6f267125] Say hello
1 file changed, 1 insertion(+)
create mode 100644 hello.py
-a
Commit all tracked files
-m
Add a commit message
Why -a
?
Instead of using -a
, you can specify individual files/directories to
commit, like git commit -m "Message" file1.py file2.py
— but this is
less common, since you’ll typically want to check in the entire repository
at a time. Do note, however, that this will commit all files that have
been changed or deleted (new files you have not told git about are not
affected).
If you leave off the -m
, Git will open up an editor for you to enter a
commit message there. We went ahead and configured Git so it uses VS Code as its
text editor.
By default, Git will use Vim as its text editor. Vim is a powerful (if difficult to
learn how to use at first) editor that comes with macOS and Linux operating
systems. Don’t be taken aback when Git uses Vim as its default text editor! This may
happen on your personal laptop or other machines you use in the future. If it opens
up Vim and you don’t know how to use it, type :q
then press Return to quit.
You can then re-type your commit command with the -m
switch.
Did it Work?¶
git status shows us the state of our repository:
$ git status
On branch main
nothing to commit, working directory clean
git log shows us a log of our revision history:
$ git log commit faa215bd9dd82ce8dca58f3ab3d0ece49d6fb351 Author: Jessica Developer <jess@gmail.com> Date: Wed Sep 17 21:13:02 2021 -0700 Say hello
A Note on Commit Messages¶
Keep messages professional and informative
Potential employers can see your Git commit messages!
Keep Working¶
Make a change to hello.py:
print('Hello')
print('World')
Git knows we’ve modified the file since we committed it:
$ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: hello.py no changes added to commit (use "git add" and/or "git commit -a")
Let’s check in our changed version:
$ git commit -a -m "Add world"
[main 411455e8] Add world
1 file changed, 1 insertion(+)
And So On¶
Keep editing and committing every so often.
Logs¶
Git Log¶
git log
shows us all history, from most recent to oldest:
$ git log commit d9808883c4432ee61c56a1df7d0c5330a5a2df7c Author: Jessica Developer <jess@gmail.com> Date: Wed Sep 17 21:17:18 2021 -0700 Add world commit faa215bd9dd82ce8dca58f3ab3d0ece49d6fb351 Author: Jessica Developer <jess@gmail.com> Date: Wed Sep 17 21:13:02 2021 -0700 Say hello
As your needs get more sophisticated, git log
has many options, such as
only showing recent history, work by one person, work on a single file or
directory of your project, etc.
Reviewing & Reverting¶
ARGH!¶
We’ve changed hello.py
print('Hello')
print('World')
Yuck
And now we’ve broken our code:
$ python3 hello.py Hello World Traceback (most recent call last): File "hello.py", line 3, in <module> Yuck NameError: name 'Yuck' is not defined
What Changed?¶
git diff can tell us what’s different:
$ git diff diff --git a/hello.py b/hello.py index 3808fc1..8ef9f2d 100644 --- a/hello.py +++ b/hello.py @@ -1,2 +1,3 @@ print("Hello") print("World") +Yuck
New lines in +green, deleted lines in -red.
Just Take Me Back¶
To return to our last revision, use git reset --hard
:
--hard
option means do this, even if we lose our changes, so be careful!
$ git reset --hard
HEAD is now at 411455e8 Add world.
Advanced resetting
You can even go back to earlier versions with git reset
by specifying
an earlier revision ID or tag — but be warned, you’re losing history
this way! This is useful only if you’re certain you never want the changes
you made after a certain revision.
To revert to an earlier revision:
$ git reset --hard finished_exercise
You can either provide a tag name or a revision ID to return to. Be careful.
Recap¶
What Did We Learn?¶
Git tracks files in “repository”
Must initialize with
git init
onceAdd files you want to track with
git add
When things work or you’ve done a lot of work, commit
Don’t be a jerk to your future self!
git status
shows status of working directorygit log
shows what you’ve committedgit diff
shows changes since you committedYou can compare to/revert back to last revision
Further Study & Resources¶
Coming Up¶
GitHub (using git in the cloud)
Git Cheatsheet¶
You can try this out, from top to bottom, with these commands:
Make a directory and go into it
$ cd ~/src $ mkdir play $ cd play
Turn into a git repository
$ git init
Add a file with one line
$ echo 'print("Hello")' > hello.py
See that git knows it’s untracked
$ git status
Tell git to track it
$ git add hello.py
Commit our change and see that it’s committed
$ git commit -a -m "Say hello" `:cmd: $ `git status $ git log
Add a second line to it
$ echo 'print("World")' > hello.py
See that git knows it changed
$ git status
Commit change and see that git tracked that
$ git commit -a -m "Add world" $ git log
Add a third, bad line to our program; see that it breaks things
$ echo 'Yuck' >> hello.py $ python3 hello.py
What changed?
$ git diff
Add the “–hard” option to say it’s ok to lose our “Yuck” line
$ git reset --hard