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:
test
bad_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 MayerowitzDate: 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.