2019 Antoine Mayerowitz
“Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.”
antoine@gitcrashcourse$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
antoine@gitcrashcourse$ brew install git
antoine@gitcrashcourse$ git config --global user.name "<My name>"
antoine@gitcrashcourse$ git config --global user.email <My email>
A git repository is like a git project folder. It contains all the history of every files in it.
There are two ways of setting a Git repository:
We will learn the first method for now !
Initiate a git repository
antoine@~$ mkdir gitcrashcourse && cd gitcrashcourse <- create a new folder and go into it
antoine@gitcrashcourse$ git init
Initialized empty Git repository in /Users/antoine/gitcrashcourse/.git/
That's it! You got your first repository
Your local repository consists of three "trees" maintained by git.
DON'T PANIC, we'll get through it in the next section
antoine@gitcrashcourse$ echo "Hello World" > hello_world.txt <- creates a text file
antoine@gitcrashcourse$ cat hello_world.txt <- print the content of our file
Hello World
See the state of your local repository
antoine@gitcrashcourse$ git status
On branch master
No commits yet
Untracked files:
(use "git add ..." to include in what will be committed)
hello_world.txt
nothing added to commit but untracked files present (use "git add" to track)
Hey look, git tells us that there is a new file!
Add file(s) to the staging state to track them.
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached file..." to unstage)
new file: hello_world.txt
Now git tracks our file, but it is not commited yet
Save tracked changes from the staging area to the HEAD.
antoine@gitcrashcourse$ git commit -m "my first commit"
[master (root-commit) acaad7c] my first commit
1 file changed, 1 insertion(+)
create mode 100644 hello_world.txt
Done!... Well ... what've changed ?
Git allows you to track changes, remember ?
See the commits history.
antoine@gitcrashcourse$ git log
Author: Antoine Mayerowitz < antoine@mayerowitz.io > <- Who
Date: Tue Apr 2 13:32:33 2019 +0200 <- When
my first commit <- What
Let's recap !
Exercise: Add changes to hello_world.txt and commit those changes!
antoine@gitcrashcourse$ date >> hello_world.txt <- Add new line with the date
antoine@gitcrashcourse$ cat hello_world.txt
Hello World
Tue Apr 2 13:48:52 CEST 2019
antoine@gitcrashcourse$ git status
On branch master
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_world.txt
no changes added to commit (use "git add" and/or "git commit -a")
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git status
On branch master
Changes to be committed:
(use "git reset HEAD < file >..." to unstage)
modified: hello_world.txt
antoine@gitcrashcourse$ git commit -m "my second commit"
[master a7a9d44] my second commit
1 file changed, 1 insertion(+)
antoine@gitcrashcourse$ git status
On branch master
nothing to commit, working tree clean
Yeah!
antoine@gitcrashcourse$ git log
commit a7a9d4417359b9a201a71fb1b1d63ac045e2abce (HEAD -> master)
Author: Antoine Mayerowitz < antoine@mayerowitz.io >
Date: Tue Apr 2 14:00:34 2019 +0200
my second commit
commit acaad7c5f17eed84ece418e3df981559de09bb01
Author: Antoine Mayerowitz < antoine@mayerowitz.io >
Date: Tue Apr 2 13:32:33 2019 +0200
my first commit
Tip: Do not edit your Master branch directly when you work within a team. It's better practice to create another branch and merge it when you are ready
antoine@gitcrashcourse$ git checkout -b development
Switched to a new branch 'development'
You can also use git branch <branchname> but you won't
checkout automatically to this branch
Let's add some experimental things to our new branch
antoine@gitcrashcourse$ echo "Experimental code" >> hello_world.txt
antoine@gitcrashcourse$ cat hello_world
Hello World
Tue Apr 2 13:48:52 CEST 2019
Experimental code
antoine@gitcrashcourse$ git status
On branch development
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_world.txt
no changes added to commit (use "git add" and/or "git commit -a")
Notice that Git tells us we are on the development branch
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git commit -m "Experimental feature"
[development 9344d4e] Experimental feature
1 file changed, 1 insertion(+)
antoine@gitcrashcourse$ git branch
* development
master
The master branch is the one created by default!
Maybe you will want to go back on master branch?
antoine@gitcrashcourse$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
antoine@gitcrashcourse$ git branch
development
* master
antoine@gitcrashcourse$ cat hello_world.txt
Hello World
Tue Apr 2 13:48:52 CEST 2019
Exercise:
testbad_idea.txt with some text in itgit branch -D <branchname>What if I want to get the changes of one branch into another?
Be sure to be on master !
antoine@gitcrashcourse$ git checkout master
antoine@gitcrashcourse$ git merge development
Updating a7a9d44..9344d4e
Fast-forward
hello_world.txt | 1 +
1 file changed, 1 insertion(+)
Let's create some modifications in development:
antoine@gitcrashcourse$ git checkout development
antoine@gitcrashcourse$ sed -i '' 's/World/Friends/' hello_world.txt <- replace World by Friends
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git commit -m "change line 1"
And also in master:
antoine@gitcrashcourse$ git checkout master
antoine@gitcrashcourse$ sed -i '' 's/World/You/' hello_world.txt
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git commit -m "change line 1"
Our two files should look like this:
master
Hello You
Tue Apr 2 13:48:52 CEST 2019
Experimental code
development
Hello Friends
Tue Apr 2 13:48:52 CEST 2019
Experimental code
What will happen when we'll merge?
Let's try to merge automatically
Don't forget to go on the master branch !
antoine@gitcrashcourse$ git merge development
Auto-merging hello_world.txt
CONFLICT (content): Merge conflict in hello_world.txt
Automatic merge failed; fix conflicts and then commit the result.
Oupsie! Guess we'll have to do it by hand.
What does our file looks like ?
<<<<<<< HEAD
Hello You
=======
Hello Friends
>>>>>>> development
Tue Apr 2 13:48:52 CEST 2019
Experimental code
We need to manually edit the file and keep our favorite version.
Don't forget to delete the git tags during the process! You can also make any other changes you like, just make it work!
Save your file when your done.
Hello Friends
Tue Apr 2 13:48:52 CEST 2019
Experimental code
Let's finish this merging !
We're close..
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git commit -m "Fix merge conflict"
[master 5059be6] Fix merge conflict
Done !
Exercise:
mastering_git.txt with some text.It's human to make some mistakes. Here are some ways to revert them.
git checkout <myfile>
antoine@gitcrashcourse$ echo "some text" >> hello_world.txt
antoine@gitcrashcourse$ cat hello_world.txt
Hello Friends
Tue Apr 2 13:48:52 CEST 2019
Experimental code
some text
antoine@gitcrashcourse$ git checkout hello_world.txt
antoine@gitcrashcourse$ cat hello_world.txt
Hello Friends
Tue Apr 2 13:48:52 CEST 2019
Experimental code
git reset HEAD <myfile>
antoine@gitcrashcourse$ echo "some staged changes" >> hello_world.txt
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
modified: hello_world.txt
antoine@gitcrashcourse$ git reset HEAD hello_world.txt <- unstaging
Unstaged changes after reset:
M hello_world.txt
antoine@gitcrashcourse$ git checkout hello_world.txt <- undo changes
git revert <myfile>
antoine@gitcrashcourse$ echo "some committed changes" >> hello_world.txt
antoine@gitcrashcourse$ git add hello_world.txt
antoine@gitcrashcourse$ git commit -m "commit to revert"
[master afd6c39] commit to revert
1 file changed, 1 insertion(+)
antoine@gitcrashcourse$ git log
commit afd6c398e5e6fe00d31d3218762be5035e635ef4 (HEAD -> master)
Author: Antoine Mayerowitz
Date: Tue Apr 2 17:29:30 2019 +0200
commit to revert
[...]
antoine@gitcrashcourse$ git revert --no-edit afd6c398e5e6fe00d31d3218762be5035e635ef4
You can also use git reset to cancel a commit but we won't cover that
.gitignore to ignore some extensions
antoine@gitcrashcourse$ zip hello_world.zip hello_world.txt
antoine@gitcrashcourse$ git status
On branch master
Untracked files:
(use "git add ..." to include in what will be committed)
hello_world.zip
antoine@gitcrashcourse$ echo "*.zip" > .gitignore <- ignore all zip files
antoine@gitcrashcourse$ git status
On branch master
Untracked files:
(use "git add < file >..." to include in what will be committed)
.gitignore <- No more zip files !
Having a gitignore in your project is great to keep it clean !
Github is a commercial website that allows users to host Git repositories. It comes with popular extra features.
We'll also need to learn a bit of extra git commands ...
But first let's create an account.
A common practice is to give the repo the same name as your directory.
We will use the third method:
antoine@gitcrashcourse$ git remote add origin https://github.com/SuperMayo/gitCourseExample.git <- Do not copy-paste !!!!
antoine@gitcrashcourse$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (20/20), 1.83 KiB | 939.00 KiB/s, done.
Total 20 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), done.
To https://github.com/SuperMayo/gitCourseExample.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
Github may ask you your credential for the first time.
Go back to your repository on Github ...
We've just seen some new functions:
You can check your remote repositories with git remote
The -u option is used only once to define the upstream (=default) remote. Then you use it like git push <remote name> <branch name>
Let's add the development branch as well.
Try to do it yourself!
antoine@gitcrashcourse$ git push origin development
What happen if someone else changes something on the remote repository ?
Let simulate that by editing directly on github!
Now go back to your console.
If I try to push new changes...
antoine@gitcrashcourse$ git add .gitignore
antoine@gitcrashcourse$ git commit -m "add gitignore"
antoine@gitcrashcourse$ git push origin master
o https://github.com/SuperMayo/gitCourseExample.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/SuperMayo/gitCourseExample.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
I get an error because my local repo is "behind" the remote.
I need to get the updates from the remote.
Git pull will download and merge the remote repo with your HEAD.
antoine@gitcrashcourse$ git pull --no-edit
Merge made by the 'recursive' strategy.
hello_world.txt | 1 +
1 file changed, 1 insertion(+)
antoine@gitcrashcourse$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
Finally, we can push our work !
antoine@gitcrashcourse$ git push origin master
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 616 bytes | 616.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/SuperMayo/gitCourseExample.git
d627d09..3e7310b master -> master
DONE !
Usually, when working within a team, you want to keep a "stable" version of your repo(most of the time it's the master branch). You also want your teammates to validate your work before merging it into master.
Let's imagine that you work on our previous project. You just created a new feature, added new data, cleaned some files ...
Go back to your console!
antoine@gitcrashcourse$ git checkout -b new-feature
antoine@gitcrashcourse$ echo "New feature to be reviewed" > feature.txt
antoine@gitcrashcourse$ git add * <- the star is a way to stage everything in our repo
antoine@gitcrashcourse$ git commit -m "New feature to do X"
antoine@gitcrashcourse$ git push origin new-feature
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 352 bytes | 352.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'new-feature' on GitHub by visiting:
remote: https://github.com/SuperMayo/gitCourseExample/pull/new/new-feature
remote:
To https://github.com/SuperMayo/gitCourseExample.git
* [new branch] new-feature -> new-feature
Now you want those changes to be reviewed by your teammates before incorporating them in the master branch.
Go back to Github!
Go on the pull request tab.
Select the branch you wish to merge.
A lot of info here. When you are ready you can create the pull request.
It's a good thing to write a message to explain what you've done!
Many other things to cover:
And many more ...
A clone is a copy of a repository that lives on your computer instead of on a website's server somewhere, or the act of making that copy. With your clone you can edit the files in your preferred editor and use Git to keep track of your changes without having to be online. It is, however, connected to the remote version so that changes can be synced between the two. You can push your local changes to the remote to keep them synced when you're online.
Contains all of the project files and stores a revision history. Think of them as project folders.
A branch is a parallel version of a repository. It is contained within the repository, but does not affect the primary or master branch allowing you to work freely without disrupting the "live" version. When you've made the changes you want to make, you can merge your branch back into the master branch to publish your changes
A commit, or "revision", is an individual change to a file (or set of files). It's like when you save a file, except with Git, every time you save it creates a unique ID (a.k.a. the "SHA" or "hash") that allows you to keep record of what changes were made when and by who. Commits usually contain a commit message which is a brief description of what changes were made.
Merging takes the changes from one branch and applies them into another.
This is the version of something that is hosted on a server (ex: Github, Gitlab, Bitbucket ...). It can be connected to local clones so that changes can be synced.
When talking about a branch or a fork, the primary branch on the original repository is often referred to as the "upstream", since that is the main place that other changes will come in from. The branch/fork you are working on is then called the "downstream".
Updates the index using the current content found in the working tree, to prepare the content staged for the next commit.
The git checkout command lets you navigate between the branches created by git branch. Checking out a branch updates the files in the working directory to match the version stored in that branch, and it tells Git to record all new commits on that branch. Think of it as a way to select which line of development you’re working on.