Git basics

This post contains the basics of using Git, the popular version control system (VCS). The post is an outline of the following video tutorial, represented by General Assembly:

Git can store different versions of your files. You can commit your files at specific points in time, and later you can jump back any point in time. Git is a distributed VCS, i.e. everyone has a copy of the repository, so you can use it locally.

(To use Git you have to download and install it.)

There is a useful reference about Git.

Creating and managing local repository

You can create a repository by typing git init in your project folder:

MBA:friends tompascall$ git init  
Initialized empty Git repository in /Users/tompascall/dev/playground/friends/.git/

It makes a .git folder in your project folder which contains your repo.

According to Git Reference, the basic work flow while using Git is:

you will use git add to start tracking new files and also to stage changes to already tracked files, then git status and git diff to see what has been modified and staged and finally git commit to record your snapshot into your history.

staging area (or index): it is a dock where you can compose what changes get recorded.

In Git, you have to add file contents to your staging area before you can commit them. Even if the file was in your last commit you still need to call git add to add new modifications to your staging area.

Let's create a file called friends.html

<!DOCTYPE html>
<html>
<head>
    <title>Friends</title>
    <meta charset="utf-8">
</head>
<body>
    <ul>
        <li>Hulk</li>
        <li>Ironman</li>
        <li>American Capitain</li>
    </ul>
</body>
</html>

Now git status shows the following:

MBA:friends tompascall$ git status
On branch master

Initial commit

Untracked files:
  (use "git add ..." to include in what will be committed)

    friends.html

nothing added to commit but untracked files present (use "git add" to track)

Then add friends.html to the stage:

$ git add friends.html

Note: You can unstaging a file by using

$ git reset friends.html

In order to see what the status of your staging area is compared to the code in your working directory, you can run the git statuscommand.

MBA:friends tompascall$ git status  
On branch master

Initial commit

Changes to be committed:  
  (use "git rm --cached ..." to unstage)

    new file:   friends.html

When you have staged the content, you can record the changes (the -m flag gives the opportunity to add some message):

MBA:friends tompascall$ git commit -m "starting friends project"  
[master (root-commit) 7a43fcb] starting friends project
 1 file changed, 14 insertions(+)
 create mode 100644 friends.html

You can track your commits:

MBA:friends tompascall$ git log --pretty=oneline  
7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 starting friends project

you can try to fancy your log by this:

MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all  
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 (HEAD, master) starting friends project

Now modify our friend.html a bit, add one more friend to the list:

<ul>
        <li>Hulk</li>
        <li>Ironman</li>
        <li>American Capitain</li>
        <li>Superman</li>
    </ul>

git status shows us that there are changes that are not be committed yet:

MBA:friends tompascall$ git status  
On branch master  
Changes not staged for commit:  
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

    modified:   friends.html

no changes added to commit (use "git add" and/or "git commit -a")

To know what changes you actually made, use git diff:

MBA:friends tompascall$ git diff  
diff --git a/friends.html b/friends.html  
index b149b98..963fa78 100644  
--- a/friends.html
+++ b/friends.html
@@ -9,6 +9,7 @@
<ul>
        <li>Hulk</li>
        <li>Ironman</li>
        <li>American Capitain</li>
+        <li>Superman</li>
    </ul>
\ No newline at end of file

After adding friends.html and committing the changes, your log is like

MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all  
* 313804335e787903e1ab16968b1b8d84333458a7 (HEAD, master) adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 starting friends project

To jump back in time, you should use git checkout with the necessary hash number. The hash number identifies the state which you want to return to, and you can figure it out when you log you commits.

git checkout 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8  
Note: checking out '7a43fcba4a14546f31e9e08da5f1f6bacde55ff8'.

You are in 'detached HEAD' state. You can look around, make experimental  
changes and commit them, and you can discard any commits you make in this  
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may  
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 7a43fcb... starting friends project

If you check your friends.html, you can see that it is changed, and nowhere is the line you added before. Of course you can anytime go back by checkout-ing a later commit.

You can check where you are in the structure of Git with log:

$ MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all  
* 313804335e787903e1ab16968b1b8d84333458a7 (master) adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 (HEAD) starting friends projectMBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all
* 313804335e787903e1ab16968b1b8d84333458a7 (master) adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 (HEAD) starting friends project

Basics of GitHub

Github is a service where you can store and share your repositories.

Supposing you have an account, you can create a new repository on GitHub. Then you can add your local repo to your new GitHub repo (origin means here GitHub):

MBA:friends tompascall$ git remote add origin git@github.com:tompascall/friends.git

You can clone a whole repository to your local machine by clone. On GitHub, you have a link at the clone section, that you should copy and paste after clone like this:

$ git clone git@github.com:username/path/repository.git

To push our local repo's history, type

MBA:friends tompascall$ git push -u origin master  
Counting objects: 6, done.  
Delta compression using up to 4 threads.  
Compressing objects: 100% (4/4), done.  
Writing objects: 100% (6/6), 581 bytes | 0 bytes/s, done.  
Total 6 (delta 1), reused 0 (delta 0)  
To git@github.com:tompascall/friends.git  
 * [new branch]      master -> master
Branch master set up to track remote branch master from origin by rebasing.

After refresh your browser, you can see your files and other repo information on your GitHub page.

Note: committing never talks to the server, it is always local. You have to use push to refresh the contents of server repository.

MBA:friends tompascall$ git push
Everything up-to-date

You can check with git log whether the HEAD points to origin (i.e. GitHub) and your master branch.

MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all  
* 313804335e787903e1ab16968b1b8d84333458a7 (HEAD, origin/master, master) adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 starting friends project

Working with others

You can edit your pushed files on GitHub. You can commit these changes at the same time, too. It may causes conflicts between the local and remote repository. Now I edited the friend.html on GitHub, and also committed. Now I can see this locally:

MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all
* fabf667c6a32cd7f658f21fea0b05311e0ec47cf (origin/master) Adding Spiderman
* 313804335e787903e1ab16968b1b8d84333458a7 (HEAD, master) adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 starting friends project

Because GitHub and your local repository don't talk to each other, you have to pull down the changes from GitHub like this>

MBA:friends tompascall$ git pull
First, rewinding head to replay your work on top of it...
Fast-forwarded master to fabf667c6a32cd7f658f21fea0b05311e0ec47cf.

And now the log looks like this:

MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all
* fabf667c6a32cd7f658f21fea0b05311e0ec47cf (HEAD, origin/master, master) Adding Spiderman
* 313804335e787903e1ab16968b1b8d84333458a7 adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 starting friends project

When more people edit the same code, there may be collisions. You can solve this the following way. Let's suppose they all committed their changes but haven't pulled or pushed yet. For example I removed Ironman on the remote repo, and the same time I moved Ironman to the end of the list. Now let's see what is happening, when I try to push my changes:

MBA:friends tompascall$ git push
To git@github.com:tompascall/friends.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:tompascall/friends.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Now I use git pull to integrate remote changes. After that friends.html looks like this:

<!DOCTYPE html>
<html>
<head>
    <title>Friends</title>
    <meta charset="utf-8">
</head>
<body>
    <ul>
<<<<<<< HEAD
        <li>Hulk</li>
=======
        <li>Hulk</li>       
>>>>>>> Ironman has been moved
        <li>American Capitain</li>
        <li>Superman</li>
        <li>Spiderman</li>
        <li>Ironman</li>
    </ul>
</body>
</html>

You have to edit your local file to solve the conflict (You have to make decision whether Ironman will be stayed or removed. You have to remove the inserted lines from file, too). After editing, friends.html looks like this:

<!DOCTYPE html>
<html>
<head>
    <title>Friends</title>
    <meta charset="utf-8">
</head>
<body>
    <ul>
        <li>Hulk</li>
        <li>American Capitain</li>
        <li>Superman</li>
        <li>Spiderman</li>
        <li>Ironman</li>
    </ul>
</body>
</html>

Then, you have to add the file to the index, then commit the changes:

MBA:friends tompascall$ git add friends.html
MBA:friends tompascall$ git commit
[detached HEAD 432f9e0] Ironman has been moved to the end.
 1 file changed, 1 insertion(+)

The commit informs you about the merging process, you can save these information (I wrote to the file the comment "Ironman has been moved to the end."). After that, git push will merge the two commits.

MBA:friends tompascall$ git push
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 295 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@github.com:tompascall/friends.git
   37cc74d..432f9e0  master -> master

Now log the changes:

MBA:friends tompascall$ git log --pretty=oneline --graph --decorate --all
* 432f9e08ce24fe8f6fb6aba9adf3da8db12a2658 (HEAD, origin/master, master) Ironman has been moved to the end.
* 37cc74df838882b53d3a004c674ec28d20421260 Ironman has been deleted.
* fabf667c6a32cd7f658f21fea0b05311e0ec47cf Adding Spiderman
* 313804335e787903e1ab16968b1b8d84333458a7 adding Superman
* 7a43fcba4a14546f31e9e08da5f1f6bacde55ff8 starting friends project

Branching

We can create a feature branch to work separately from master branch, and later we can merge our changes to master branch. A branch is like a separate line of commits.

$ git checkout -b your-branch-name

You can switch to master branch by git checkout master.

To merge your feature branch into master branch, first you have to switch to master branch. Then you have to merge your branch:

$ git merge your-branch-name

(You can save the merging information in a text file like above at the merging conflict).



comments powered by Disqus