dropdown menu


Git Basics

The purpose of Git is to keep track of the changes, which have been made on files. In more official wording: Git is a distributed version control system. Version Control System can be any software that records changes to files over time so that you can recall specific versions later. It helps software teams to keep track of modifications to the source code. If a mistake is made, developers can turn back the clock and compare earlier versions of the code to help fix the mistake. (Git was created by Linus Torvalds in 2005 to help during the development of the Linux Kernel with other kernel developers.)

Git is distributed, which means everyone has a local copy of all the files, so they can work independently of a central server. (In opposite, a Central Version Control system is  located in one place, and people can check out from the central location, make changes and check everything back in.)

When someone completes a task, he needs to do a commit. Commit is a snapshot of the state of your files, plus some metadata (such as who made the commit and when, with a comment, and a pointer to the previous commits). Every time you commit, or save the state of your project, Git basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot. As time goes by, each commit is pointing to its parent to keep track all the changes that have been made:

Arrows are identifying a commit's parent (pointing to the left)

Some terminology:
-repository - this is where git stores all details, metadata which is needed for tracking (.git directory in the project dir)
-commit     - record changes to the repository (the local one)
-branch     - like in a tree, another path is taken in the main line of development, so the main line keeps untouched
-merge      - will take the independent lines of development (branches) and integrate them into a single branch
-master     - the repository’s main branch, usually other branches are checked out from this
-clone      - copies an existing git repository, which we don't have, (it is usually used only once)
-fetch      - downloads commits, files ...from a remote repository into your local repo and updates that local copy
-pull       - fetch (download) content from a remote repository and update local repository. (git fetch followed by git merge)
-push       - is used to submit the code to a remote repository
-head       - is a reference which points to the last commit we have made.
-checkout   - switch to another branch. To prepare working on a branch. (Pointing the head to that branch)


Repository (.git directory)

Git stores all necessary information, metadata (which is needed to track all changes) in a data structure called a repository. The Git repository is in the same directory as the project itself, in a subdirectory called .git. You can obtain a Git repository in one of two ways:

1. You can take a local directory that is currently not under version control, and turn it into a Git repository.
You can go to any directory and use the command: git init. This creates a new subdirectory named .git that contains all of your necessary repository files. At this point, nothing in your project is tracked yet. If you want to start version-controlling existing files , you need to track those files (with git add) and do an initial commit (git commit).

2. You can clone an existing Git repository from elsewhere.
If you want to get a copy of an existing Git repository, "git clone" needs to be used. Then Git receives a full copy of all data that the server has. Every version of every file for the history of the project is pulled down by default

git clone <url>                         <--clone a repository to the current directory
git clone <url> <new name>              <--clone the repository into a directory named something other


Working with Git

During our work in Git (using specific Git commands) our files can be in different states:
-Committed: It means that the data is safely stored in your local database.
-Staged: It means that you have marked a modified file in its current version to go into your next commit.
-Modified: It means that you have changed the file but have not committed it to your database yet.

The basic Git workflow goes something like this: 
You switch to the project you would like to work with command: git checkout. The you start to work in your working directory and modify files there. After finishing some work, you mark the files you have been worked on with command: git add. This will stage those files to be part of the next commit. In other words it will add those changes (files) to the staging area. After that when you do a commit, it will take the files as they are in the staging area and stores that snapshot permanently to your Git directory.

The .git directory is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer. If a particular version of a file is in the Git directory, it’s considered committed.

The staging area is a file, generally contained in your .git directory, that stores information about what will go into your next commit. If a file has been modified and was added to the staging area (with the command git add), it is staged.

The working directory (sometimes it is called working tree) is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.

Everything in Git is check-summed before it is stored (committed) and is then referred to by that checksum. This means it’s impossible to change the content of a file or directory without Git knowing about it. The mechanism that Git uses for this checksumming is called a SHA-1 hash. This is a 40-character string.


Starting to work with git

After install (like yum install git) some configuration is needed, for example to add your name to the checkouts and changes.
Config details can be seen by "git config --list" and changing configs can be done:

git config --global user.name "<user name>"
git config --global user.email "<user email>"

After that we can start to initialize a directory to be tracked by git:
1. go to the directory you would like to track
2. git init (it will create a .git directory which contains all details needed for tracking)
3. git status (show status of files if those are up to date, tracked etc..)

If there are files we don't want to track create .gitignore file:
# vi .gitignore:

If this file exists "git status" will not show that file.


Adding files to Staging area

When a new file is created it is not tracked automatically by Git. Git needs to be informed directly to track that file with git add. If you modify the file after you run git add, you have to run git add again to stage the latest version of the file. Otherwise the version when it was when you last ran the git add command will go into the commit, not the version of the file as it looks now.

This message can pop up in this case: “Changes not staged for commit”:
It means that a file that is tracked has been modified in the working directory but not yet staged. To stage it, you need to the git add command, which is a multipurpose command. You use it to begin tracking new files, to stage files, and to do other things. It may be helpful to think of it more as "add precisely this content to the next commit"


Committing files:

When your staging area is set up, you can commit your changes. The usage is, git commit -m "Some message". If -m is omitted an editor will be popped up to put commit message there. With the commit, which will do a snapshot of the actual state of the staged files, these things will be saved: who did the commit, commit date, what SHA-1 checksum the commit has, what is the commit message etc.
(The commit records the snapshot you set up in your staging area. Anything you didn’t stage is still sitting there modified.)

1. git add -A                   <--add everything to the staging area
2. git status                   <--show the status
3. git diff                     <--shows changes made to the code
3. git commit -m "message"      <--committing files in the staging area (adds file to the repository)
4. git log                      <-- will show the commit what we made (hash number, name , date, message)

(git commit command commits only to the local branch we are working on and has no effect on other local branches, and it has no effect on remote repository as well)



git config --help                <--help
git --version                    <--check version
git init                         <--turn a directory into git repository (.git subdir is added with metadata)
rm -rf .git                      <--stop git tracking that directory by git (remove .git subdirectory)
.gitignore                       <--this file contains all the files which will be ignored from git
git status                       <--show the actual status of the working dir
git log                          <--shows commit history with hashes, dates, messages
git log --stat                   <--shows which files have been changed and part of the commit
git reflog                       <--shows in order check-outs, commits, resets

git add <file>                   <--adds a files to tracking (or if it is tracked puts in staging, which is needed before commit)
git add -A                       <--adds all files in current dir for tracking or to the staging area (git add . is the same)
git mv <file_old> <file_new>     <--rename a file in Git

git rm --cached  <file>          <--remove a file from git tracking (keeps the file on your hard drive but Git will not track)
git rm <file>                    <--remove a file from git tracking and from working dir (deletes from hard drive)(commit is needed)
git rm -f <file>                 <--if file is already added to staging area, then  -f option (force) is needed for removal
git reset <filename>             <--remove files from the staging area, unstaging a staged file
git reset                        <--will remove everything from the staging area

git commit -m "<message>"            <--commit  with a message
git commit --amend -m "new message"  <--change commit message to a new message
git commit --amend                   <--if we missed a file from last commit and want that to be part of that last commit
                                     (it brings up a vi editor, just save it: wq)

git branch                       <--list all local branches (* will show which branch we are currently working on)
git branch --merged              <--lists the branches that have been merged already
git branch -a                    <--lists all the branches of the repository (not only locally, remotely as well)
git branch -r                    <--lists all remote branches
git branch <new branch name>     <--create a branch
git branch -d <branch>           <--deletes branch locally

git checkout <branch name>       <--changing to the given branch (so we that given branch
git checkout --<filename>        <--if a file is modified and we want to dismiss modifications and go back to the original state


git remote                       <--lists remote servers you have configured (shortname)
git remote -v                    <--shows you the URLs that Git has stored for the shortname
git remote show <remote>         <--show more information about a particular remote

git remote add <shortname> <url>  <--add a new remote Git repository as a shortname to reference
git remote add origin <url>       <--will create new remote (called origin) located at the specified link
git remote rename <current> <new> <--change a remote’s shortname from <current> to <new>
git remote remove <remote>        <--remove a remote

git clone <url> <where to clone>  <-- clone remote repository to given location
git clone ../remote_repo.git .    <--cloning example

If you clone a repository, the command automatically adds that remote repository under the name "origin". So, "git fetch origin" fetches any new work that has been pushed to that server since you cloned (or last fetched from) it. (git fetch will not do merge, just download the data)

If your current branch is set up to track a remote branch, you can use the git pull command to automatically fetch and then merge that remote branch into your current branch. By default, the git clone command automatically sets up your local master branch to track the remote master branch on the server you cloned from. Running git pull fetches data from the server you originally cloned from and automatically tries to merge it into the code you’re currently working on.

git fetch <remote>                <--get data from a remote project, it pulls down all the data from that remote project
git pull                          <--it is a combination of 2 comands: git fetch + git merge
git pull origin master            <--pulls any changes since the last time we have pulled from a repository

git push origin master            <-- push your master branch to your origin server
git push <remote> <branch>        <--submit branch to the remote repository
git push -u origin <branch name>  <--- -u is doing association between origin and our branch


git diff <file>                             <--shows what exactly has been changed in given file
git diff <hash1> <hash2>                    <--show difference between hashes
git diff <source_branch> <target_branch>    <--doing a preview before a merge
git revert                                  <--will revert everything ???

git tag                                     <--showing tags (these are the versions which are added to  commits)
git tag -a v1.0 -m "Version 1.0 release"    <--point to the current release


Fixing (undoing) a commit (git commit --amend):
(Committing accidentally too early and possibly forget to add some files, or we mess up our commit message.)

If we did a commit and then realize we forgot to stage the changes in a file we wanted to add to this commit, then we can use "git commit --amend" to fix this:
1. git commit -m "<initial commit>"
2. git add <forgotten file>
3. git commit --amend

The second commit replaces the first, as a result we end up with a single commit, and the earlier commit will not show up in the repository history

This command takes the staging area and uses it for the commit. If there are no changes since the last commit (if we run this command immediately after a commit) then only the commit message can be changed. A commit-message editor pops up, which already contains the message of our previous commit, which we can change and save.


Branch and Merge:

1. git branch                      <--shows how many branches we have (* shows which branch we are currently on)
2. git branch <name>               <--create a new branch
3. git checkout <branch>           <--switch to the given branch
4. do some work there

Merging a branch to master (locally and remotely)
(All merging is done into the branch where you are.)

1. git checkout master             <--switch to our master branch
2. git pull origin master          <--pull the changes down to make sure if there were any changes by others we have those
3. git branch --merged             <--lists the branches that have been merged already (our branch is not on the list)
4. git merge <branch name>         <--merge given branch to where we are (currently it is master)

After merging branch to the master (local), these changes can be pushed to the remote master:
git push origin master             <--all these changes are pushed to the master on the remote repository


Deleting a branch

After we finished merging our branch, that feature is done and we can delete that branch:
1. git branch --merged             <--just to double check everything was successfully merged
2. git branch -d <branch>          <--deletes branch locally

If we pushed that branch to the remote repository, we can delete from there as well:
git branch -a                      <--list branches (our local branch is not there anymore, but we still have on remote repository)
git push origin --delete <branch>  <--to delete a branch on remote repository


Fixing an accidental commit to a wrong branch:
(moving a commit to another branch)

1. git log                         <--check the hash of the commit you want to move (only first 6-8 characters)
2. git checkout <branch>           <--switch to the branch (you can check git log again)
3. git cherry-pick <hash>          <--it will bring over the given commit to the branch where I am

We still have the commit on the master branch (cherry-pick will not delete that). To delete that from the master branch:
4. git checkout master             <--switch to master branch
5. git log                         <--check hash and commits
6. git reset ….                    <--reset back a specified commit, it has 3 types (soft, mixed, hard):
        git reset --soft <hash>    <--reset back a commit, but will keep files in staging area
        git reset --mixed <hash>   <--(default) it is same as soft, but files will be not in staging area, instead in the working dir
        git reset --hard <hash>    <--reset all tracked file to the state that they were (it leaves any untracked file there)
7. git clean -df                   <--after git reset, get rid of any untracked directories (-d) and untracked file (-f)


No comments: