Sunday, 26 March 2017

Introduction to GIT

Version control systems allow you to keep track of your software at the source level. You can track changes, revert to previous stages, and branch off from the base code to create alternative versions of files and directories.
Git is an open source, distributed version control system (VCS). It’s commonly used for source code management (SCM), with sites like GitHub offering a social coding experience, and popular projects such as Perl, Ruby on Rails, and the Linux kernel using it.

Git has released 2.8.11 version on Nov 24, 2016. Git is a free and open source distributed version control system. It is designed to handle a small to very large projects with speed and efficiency. To read more details and changes about Git 2.8.11 read Git release notes
These instructions are intended for installing Git on Linux Environment.
Before installing Git from source code, make sure you have already installed required packages on your system. If not use the following command to install required packages.

Installation of git in CentOS

Step 1: Installing Required Packages

# yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel  perl-ExtUtils
# yum install gcc perl-ExtUtils-MakeMaker

# sudo yum install git

You’ll be asked to confirm the download and installation; simply enter y to confirm. Once this command is complete, git will be installed and ready to use!
If the command completes without error, you will have git downloaded and installed. To double-check that it is working correctly, try running Git's built-in version check:
   git –version     

Install Method 2 :

Download latest Git source code from kernel git or simply use following command to download Git 2.8.11.

# cd /usr/src
# wget https://www.kernel.org/pub/software/scm/git/git-2.8.11.tar.gz
# tar xzf git-2.8.11.tar.gz

After downloading and extracting Git source code, Use the following command to compile the source code.

# cd git-2.8.11
# make prefix=/usr/local/git all
# make prefix=/usr/local/git install

After installation of git client. Now you must need to set binary in system environment. So edit /etc/bashrc file and add below content to it
 # export PATH=$PATH:/usr/local/git/bin

OR

echo "export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc
source /etc/bashrc

Now execute below command to reload configuration in current environment.
# source /etc/bashrc

After completing above steps. Let’s use following command to check current git version.
# git --version

git version 2.8.11

Before you begin, you'll need to install the software that git depends on. These dependencies are all available in the default CentOS repositories, along with the tools that we need to build a binary from source:

sudo yum groupinstall "Development Tools"

sudo yum install gettext-devel openssl-devel perl-CPAN perl-devel zlib-devel

After you have installed the necessary dependencies, you can go ahead and look up the version of Git that you want by visiting the project's releases page on GitHub.
https://github.com/

The version at the top of the list is the most recent release. If it does not have -rc (short for "Release Candidate") in the name, that means that it is a stable release and is safe for use. Click on the version you want to download to be taken to that version's release page. Then right-click on the Source code (tar.gz) button and copy the link to your clipboard.
The version at the top of the list is the most recent release. If it does not have -rc (short for "Release Candidate") in the name, that means that it is a stable release and is safe for use. Click on the version you want to download to be taken to that version's release page. Then right-click on the Source code (tar.gz) button and copy the link to your clipboard.

Now we are going to use the wget command in our CentOS server to download the source archive from the link that we copied, renaming it to git.tar.gz in the process so that it is easier to work with.
Note: the URL that you copied may be different from mine, since the release that you download may be different.
wget https://github.com/git/git/archive/v2.1.2.tar.gz -O git.tar.gz
Once the download is complete, we can unpack the source archive using tar. We'll need a few extra flags to make sure that the unpacking is done correctly: z decompresses the archive (since all .gz files are compressed), x extracts the individual files and folders from the archive, and f tells tar that we are declaring a filename to work with.
tar -zxf git.tar.gz
This will unpack the compressed source to a folder named after the version of Git that we downloaded (in this example, the version is 2.1.2, so the folder is named git-2.1.2). We'll need to move to that folder to begin configuring our build. Instead of bothering with the full version name in the folder, we can use a wildcard (*) to save us some trouble in moving to that folder.
cd git-*
Once we are in the source folder, we can begin the source build process. This starts with some pre-build checks for things like software dependencies and hardware configurations. We can check for everything that we need with the configure script that is generated by make configure. This script will also use a --prefix to declare /usr/local (the default program folder for Linux platforms) as the appropriate destination for the new binary, and will create a Makefile to be used in the following step.
make configure
./configure --prefix=/usr/local

Makefiles are scriptable configuration files that are processed by the make utility. Our Makefile will tell make how to compile a program and link it to our CentOS installation so that we can execute the program properly. With a Makefile in place, we can now execute make install (with sudo privileges) to compile the source code into a working program and install it to our server:
sudo make install

This will install the make tools and compilers needed to transform source code into binary executables.Once this is complete, we will need to install some extra dependencies that git needs either to build or run:
sudo yum install zlib-devel perl-ExtUtils-MakeMaker asciidoc xmlto openssl-devel

Once these are installed, you can obtain the latest version of git from the code hosted on github.com:
cd ~

Unzip the archive and change into the project directory:
unzip git.zip
cd git-master
We can figure the package, build the executables and documentation, and then install it with the following set of commands:
make configure
./configure --prefix=/usr/local
make all doc
sudo make install install-doc install-html

To update git at a later date, you can actually use git! Clone the git repository on github into a new directory and then build and install it, as before:
git clone git://github.com/git/git

Installation on Ubuntu 14.04 

By far the easiest way of getting git installed and ready to use is by using Ubuntu's default repositories. This is the fastest method, but the version may be older than the newest version. If you need the latest release, consider following the steps to compile git from source.
You can use the apt package management tools to update your local package index. Afterwards, you can download and install the program:

sudo apt-get update
sudo apt-get install git-all

Installing from Source

Some people may instead find it useful to install Git from source, because you’ll get the most recent version. The binary installers tend to be a bit behind, though as Git has matured in recent years, this has made less of a difference.
If you do want to install Git from source, you need to have the following libraries that Git depends on: autotools, curl, zlib, openssl, expat, and libiconv. For example, if you’re on a system that has yum (such as Fedora) or apt-get (such as a Debian based system), you can use one of these commands to install the minimal dependencies for compiling and installing the Git binaries:

$ sudo apt-get update
$ sudo yum install dh-autoreconf curl-devel expat-devel gettext-devel \
  openssl-devel perl-devel zlib-devel
$ sudo apt-get install dh-autoreconf libcurl4-gnutls-dev libexpat1-dev \
  gettext libz-dev libssl-dev
$ sudo apt-get install build-essential libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext unzip


In order to be able to add the documentation in various formats (doc, html, info), these additional dependencies are required (Note: users of RHEL and RHEL-derivatives like CentOS and Scientific Linux will have to enable the EPEL repository to download the docbook2X package):

$ sudo yum install asciidoc xmlto docbook2X getopt
$ sudo apt-get install asciidoc xmlto docbook2x getopt

Additionally, if you’re using Fedora/RHEL/RHEL-derivatives, you need to do this

$ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi

The version you see when you arrive at the project's page is the branch that is actively being committed to. If you want the latest stable release, you should go change the branch to the latest non-"rc" tag using this button along the left side of the project header:

Next, on the right side of the page, right-click the "Download ZIP" button and select the option similar to "Copy Link Address":

Back on your Ubuntu 14.04 server, you can type wget and follow it by pasting the address you copied. The URL that you copied may be different from mine:
  wget https://github.com/git/git/archive/v1.9.2.zip -O git.zip

Unzip the file that you downloaded and move into the resulting directory by typing:

unzip git.zip
cd git-*

Now, you can make the package and install it by typing these two commands:

make prefix=/usr/local all
sudo make prefix=/usr/local install

Now that you have git installed, if you want to upgrade to a later version, you can simply clone the repository and then build and install:

git clone https://github.com/git/git.git

To find the URL to use for the clone operation, navigate to the branch or tag that you want on the project's GitHub page and then copy the clone URL on the right side:


This will create a new directory within your current directory where you can rebuild the package and reinstall the newer version, just like you did above. This will overwrite your older version with the new version:

make prefix=/usr/local all
sudo make prefix=/usr/local install

We can see all of the configuration items that have been set by typing:

git config --list

 The information is stored in the configuration file, which you can optionally edit by hand with your text editor like this:

nano ~/.gitconfig

~/.gitconfig contents
[user]
    name = Your Name
    email = youremail@domain.com

There are many other options that you can set, but these are the two essential ones needed. If you skip this step, you'll likely see warnings when you commit to git that are similar to this:
Output when git username and email not set

[master 0d9d21d] initial project version
 Committer: root
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:
    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

When you have all the necessary dependencies, you can go ahead and grab the latest tagged release tarball from several places. You can get it via the Kernel.org site, at https://www.kernel.org/pub/software/scm/git, or the mirror on the GitHub website, at https://github.com/git/git/releases. It’s generally a little clearer what the latest version is on the GitHub page, but the kernel.org page also has release signatures if you want to verify your download.

Then, compile and install:

$ tar -zxf git-2.0.0.tar.gz
$ cd git-2.0.0
$ make configure
$ ./configure --prefix=/usr
$ make all doc info
$ sudo make install install-doc install-html install-info

After this is done, you can also get Git via Git itself for updates:

$ git clone git://git.kernel.org/pub/scm/git/git.git

Checking the Git Version

The above steps successfully install the Git in software on your system. However, Git is a highly versatile software that comes in various versions to suit the requirements of users across the board. Every version has different commands to fetch the desired data. So, before you start using this software, you should know exactly what version you are using. This will help you to derive the desired results quickly. The command to check the version of Git is:
$ git -version


Installing on Windows

There are also a few ways to install Git on Windows. The most official build is available for download on the Git website. Just go to http://git-scm.com/download/win and the download will start automatically. Note that this is a project called Git for Windows, which is separate from Git itself; for more information on it, go to https://git-for-windows.github.io/.
To get an automated installation you can use the Git Chocolatey package. Note that the Chocolatey package is community maintained.
Another easy way to get Git installed is by installing GitHub for Windows. The installer includes a command line version of Git as well as the GUI. It also works well with Powershell, and sets up solid credential caching and sane CRLF settings. We’ll learn more about those things a little later, but suffice it to say they’re things you want. You can download this from the GitHub for Windows website, at http://windows.github.com.

Initial Git Set Up

Now that you have successfully installed Git in your system, you would be eager to customize the software as per your own requirements. Customization of Git is rather easy and once done it remains there even if your upgrade the software. In case you want to change them, you can do so simply by repeating the commands.

With Git you have the convenience of gitconfig, an effective tool that allows you to set configuration variables as per your needs. These variables ultimately decide how your software looks and operates. You can store these variables in three different places: " /etc/gitconfig file: This file stores the values and repositories of all the system users. When the option - -system to gitconfig is pressed, Git reads and writes from this file only. " ~/.gitconfig file: This file is user specific and when you pass the option -global, Git reads and writes specifically to this file. " config file in the Git directory (that is, .git/config) of the repository you're using: This file is again specific to the single repository that you are currently using. In this file each level overrides values in the previous level and consequently the values in .git/config file override the values in /etc/gitconfig.

When you are using a Windows system, Git looks for the .gitconfig file in the $HOME directory (%USERPROFILE% in Windows' environment), which is C:\Documents and Settings\$USER or C:\Users\$USER for most people, depending on version ($USER is %USERNAME% in Windows' environment). Though Git is relative to the Msys root, it still looks for /etc/gitconfig when you install it on your Windows system or when you run the installer.

First-Time Git Setup

Now that you have Git on your system, you’ll want to do a few things to customize your Git environment. You should have to do these things only once on any given computer; they’ll stick around between upgrades. You can also change them at any time by running through the commands again.
Git comes with a tool called git config that lets you get and set configuration variables that control all aspects of how Git looks and operates. These variables can be stored in three different places:
·       /etc/gitconfig file: Contains values for every user on the system and all their repositories. If you pass the option --system to git config, it reads and writes from this file specifically.
·       ~/.gitconfig or ~/.config/git/config file: Specific to your user. You can make Git read and write to this file specifically by passing the --global option.
·       config file in the Git directory (that is, .git/config) of whatever repository you’re currently using: Specific to that single repository.
Each level overrides values in the previous level, so values in .git/config trump those in /etc/gitconfig.
On Windows systems, Git looks for the .gitconfig file in the $HOME directory (C:\Users\$USER for most people). It also still looks for /etc/gitconfig, although it’s relative to the MSys root, which is wherever you decide to install Git on your Windows system when you run the installer. If you are using version 2.x or later of Git for Windows, there is also a system-level config file at C:\Documents and Settings\All Users\Application Data\Git\config on Windows XP, and in C:\ProgramData\Git\config on Windows Vista and newer. This config file can only be changed by git config -f <file> as an admin.

Setting up User Identity

Whenever you install the Git software in your system the most important thing to do is setting your user name and email address. In fact, this should be your first task as every Git commit uses these credentials and the information provided in them remains unchanged when you pass around.

$ gitconfig --global user.name "John Doe"
$ gitconfig --global user.email peterdrucker@sample.com
Again, you need to do this only once if you pass the --global option, because then Git will always use that information for anything you do on that system. If you want to override this with a different name or email address for specific projects, you can run the command without the --global option when you’re in that project.
Many of the GUI tools will help you do this when you first run them.

Your Editor

Now that your identity is set up, you can configure the default text editor that will be used when Git needs you to type in a message. If not configured, Git uses your system’s default editor.

If you want to use a different text editor, such as Emacs, you can do the following:

$ git config --global core.editor emacs

While on a Windows system, if you want to use a different text editor, such as Notepad++, you can do the following:

On a x86 system
$ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst –nosession”
On a x64 system
$ git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -nosession"
Checking Your Settings

Next we’ll verify the configuration changes by viewing the .gitconfig . Since you may have been roaming around your server’s file system before starting this tutorial, use the cd command to return to your home directory:
cd
And then view the .gitconfig :

cat .gitconfig

You can also view the same details of your configuration by using the following command:

git config --list

If you want to check your settings, you can use the git config --list command to list all the settings Git can find at that point:
$ git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
You may see keys more than once, because Git reads the same key from different files (/etc/gitconfigand ~/.gitconfig, for example). In this case, Git uses the last value for each unique key it sees.
You can also check what Git thinks a specific key’s value is by typing git config <key>:

$ git config user.name
John Doe

The configuration changes will be stored in a file in your home directory. You can see them with a normal text editor:
nano ~/.gitconfig
[user]
        name = Your Name Here
        email = your_email@example.com

You can also view this information by querying git itself for the current configuration settings:
git config --list
user.name=Your Name Here
user.email=your_email@example.com

As mentioned earlier, if you forget to set up these steps, git may try to fill in these values automatically:
[master 0d9d21d] initial project version
 Committer: root
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:

    git config --global user.name "Your Name"
    git config --global user.email you@example.com

After doing this, you may fix the identity used for this commit with:

    git commit --amend --reset-author

Depending on your version of git, it may fail entirely:
git commit
*** Please tell me who you are.
Run
  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
 fatal: empty ident name (for ) not allowed
Configuring the Editor for the User

Once you have set up your identity, you can configure the default text editor in your system. Git uses this editor by default whenever you type a message. Most of the systems have Vi or Vim as the default editor; however if you want to use a different editor like Emacs etc. you can use the following command:

Configuring the Diff Tool

The default diff tool is one of the highly recommended options for Git users. This is because the option comes as a handy tool to resolve minor day-to-day conflicts. There are a variety of such applications available for you; vimdiff being the most common. To configure vimdiff in your system you can use the command:

gitconfig --global merge.tool vimdiff
Git being a widely used software is compatible with most of the diff tools. The most commonly used diff tools include kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff.

Checking Your Settings

Another highly effective feature of Git is that it allows you go check your setting at any given point in time. The single command gitconfig -list gives you a complete list of all your settings. Once you pass the command $gitconfig -list you will get the details as:

user.name=JohnDoe
user.email=jdoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto

As Git reads the same key from different files, you may see the same key many times on the screen. For example if Git is reading the same key from /etc/gitconfig and /gitconfig files, it will use the last value represented by the key. In such a case, you may find out how Git is giving value to a specific by using the command:

gitconfig{key}:

$ gitconfig user.name
LizTaylor

Seeking Help

Though Git is a highly versatile software, at times you may need help while using it. However, getting help on Git is as easy as using it. It offers three different ways to access the manual page (manpage):

git help
git --help
mangit-
For example, to get manpage help for the config command, you simply have to use the following command:

git help config

The best part about the manpage help is that you can access is anytime and anywhere. Git offers you the manpage help even when you are offline. Some beginners and even seasoned users need in-person help for certain tasks on Git. Round-the-clock help is available for such users at #git or #github channels on the Freenodes IRC server. These channels have a heavy presence of seasoned Git users who are willing to help their fellow users.

$ git help <verb>
$ git <verb> --help
$ man git-<verb>

For example, you can get the manpage help for the config command by running

$ git help config

Git – Create Remote Repository

Create System User

First create a system user, which will be used to connect repository on server from client systems.
$ sudo adduser git

Adding user git' ...
Adding new group git' (1044) ...
Adding new user git' (1044) with group git' ...
Creating home directory /home/git' ...
Copying files from /etc/skel' ...
Enter new UNIX password: *********
Retype new UNIX password: *********
passwd: password updated successfully
Changing the user information for git
Enter the new value, or press ENTER for the default
   Full Name []:
   Room Number []:
   Work Phone []:
   Home Phone []:
   Other []:
Is the information correct? [Y/n] y

 Create Bare Repository

Now create a git bare repository. This repository will be used as remote repository by developers. First we are creating a project directory. After that I will create our first git repository named app1.git inside project directory. Try to keep repository name ending with .git for better naming convention.

$ mkdir project
$ cd project

$ mkdir app1.git
$ cd app1.git

Now use following command to initialize repository. Do not forgot to use –bare keyword in command to create bare repository.
$ git --bare init

Initialized empty Git repository in /home/git/project/app1.git/
If you list files inside repository you will not find directory named .git due to bare repository, You will see their many files like below

$ ls -l
total 32
drwxrwxr-x 2 git git 4096 Oct  8 12:33 branches
-rw-rw-r-- 1 git git   66 Oct  8 12:33 config
-rw-rw-r-- 1 git git   73 Oct  8 12:33 description
-rw-rw-r-- 1 git git   23 Oct  8 12:33 HEAD
drwxrwxr-x 2 git git 4096 Oct  8 12:33 hooks
drwxrwxr-x 2 git git 4096 Oct  8 12:33 info
drwxrwxr-x 4 git git 4096 Oct  8 12:33 objects
drwxrwxr-x 4 git git 4096 Oct  8 12:33 refs

 Access Repository From Dev PC

Now you can make a clone of this repository from clients system using following command.


Getting a Git Repository

You can get a Git project using two main approaches. The first takes an existing project or directory and imports it into Git. The second clones an existing Git repository from another server.

Initializing a Repository in an Existing Directory

If you’re starting to track an existing project in Git, you need to go to the project’s directory. If you’ve never done this, it looks a little different depending on which system you’re running:

for Linux:
$ cd /home/user/your_repository
for Mac:
$ cd /Users/user/your_repository
for Windows:
$ cd /c/user/your_repository
$ git init

This creates a new subdirectory named .git that contains all of your necessary repository files – a Git repository skeleton. At this point, nothing in your project is tracked yet. (See Git Internals for more information about exactly what files are contained in the .git directory you just created.)
If you want to start version-controlling existing files (as opposed to an empty directory), you should probably begin tracking those files and do an initial commit. You can accomplish that with a few git addcommands that specify the files you want to track, followed by a git commit:

$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'

We’ll go over what these commands do in just a minute. At this point, you have a Git repository with tracked files and an initial commit.

Recording Changes to the Repository

You have a bona fide Git repository and a checkout or working copy of the files for that project. You need to make some changes and commit snapshots of those changes into your repository each time the project reaches a state you want to record.
Remember that each file in your working directory can be in one of two states: tracked or untracked. Tracked files are files that were in the last snapshot; they can be unmodified, modified, or staged. Untracked files are everything else – any files in your working directory that were not in your last snapshot and are not in your staging area. When you first clone a repository, all of your files will be tracked and unmodified because Git just checked them out and you haven’t edited anything.
As you edit files, Git sees them as modified, because you’ve changed them since your last commit. You stage these modified files and then commit all your staged changes, and the cycle repeats.


Checking the Status of Your Files

The main tool you use to determine which files are in which state is the git status command. If you run this command directly after a clone, you should see something like this:

$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
This means you have a clean working directory – in other words, none of your tracked files are modified. Git also doesn’t see any untracked files, or they would be listed here. Finally, the command tells you which branch you’re on and informs you that it has not diverged from the same branch on the server. For now, that branch is always “master”, which is the default; you won’t worry about it here. Git Branching will go over branches and references in detail.

Let’s say you add a new file to your project, a simple README file. If the file didn’t exist before, and you run git status, you see your untracked file like so:

$ echo 'My Project' > README
$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    README

Nothing added to commit but untracked files present (use "git add" to track)
You can see that your new README file is untracked, because it’s under the “Untracked files” heading in your status output. Untracked basically means that Git sees a file you didn’t have in the previous snapshot (commit); Git won’t start including it in your commit snapshots until you explicitly tell it to do so. It does this so you don’t accidentally begin including generated binary files or other files that you did not mean to include. You do want to start including README, so let’s start tracking the file.

Tracking New Files

In order to begin tracking a new file, you use the command git add. To begin tracking the README file, you can run this:
$ git add README
If you run your status command again, you can see that your README file is now tracked and staged to be committed:

$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
You can tell that it’s staged because it’s under the “Changes to be committed” heading. If you commit at this point, the version of the file at the time you ran git add is what will be in the historical snapshot. You may recall that when you ran git init earlier, you then ran git add (files) – that was to begin tracking files in your directory. The git add command takes a path name for either a file or a directory; if it’s a directory, the command adds all the files in that directory recursively.

Staging Modified Files

Let’s change a file that was already tracked. If you change a previously tracked file called CONTRIBUTING.md and then run your git status command again, you get something that looks like this:
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README

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:   CONTRIBUTING.md

The CONTRIBUTING.md file appears under a section named “Changes not staged for commit” – which means that a file that is tracked has been modified in the working directory but not yet staged. To stage it, you run the git add command. git add is a multipurpose command – you use it to begin tracking new files, to stage files, and to do other things like marking merge-conflicted files as resolved. It may be helpful to think of it more as “add this content to the next commit” rather than “add this file to the project”. Let’s run git add now to stage the CONTRIBUTING.md file, and then run git status again

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Both files are staged and will go into your next commit. At this point, suppose you remember one little change that you want to make in CONTRIBUTING.md before you commit it. You open it again and make that change, and you’re ready to commit. However, let’s run git status one more time:

$ vim CONTRIBUTING.md
$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

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:   CONTRIBUTING.md

What the heck? Now CONTRIBUTING.md is listed as both staged and unstaged. How is that possible? It turns out that Git stages a file exactly as it is when you run the git add command. If you commit now, the version of CONTRIBUTING.md as it was when you last ran the git add command is how it will go into the commit, not the version of the file as it looks in your working directory when you run git commit. If you modify a file after you run git add, you have to run git add again to stage the latest version of the file:

$ git add CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   README
    modified:   CONTRIBUTING.md

Short Status

While the git status output is pretty comprehensive, it’s also quite wordy. Git also has a short status flag so you can see your changes in a more compact way. If you run git status -s or git status --short you get a far more simplified output from the command:

$ git status -s
 M README
MM Rakefile
A  lib/git.rb
M  lib/simplegit.rb
?? LICENSE.txt

New files that aren’t tracked have a ?? next to them, new files that have been added to the staging area have an A, modified files have an M and so on. There are two columns to the output - the left-hand column indicates the status of the staging area and the right-hand column indicates the status of the working tree. So for example in that output, the README file is modified in the working directory but not yet staged, while the lib/simplegit.rb file is modified and staged. The Rakefile was modified, staged and then modified again, so there are changes to it that are both staged and unstaged.

Ignoring Files

Often, you’ll have a class of files that you don’t want Git to automatically add or even show you as being untracked. These are generally automatically generated files such as log files or files produced by your build system. In such cases, you can create a file listing patterns to match them named .gitignore. Here is an example .gitignore file:

$ cat .gitignore
*.[oa]
*~

The first line tells Git to ignore any files ending in “.o” or “.a” – object and archive files that may be the product of building your code. The second line tells Git to ignore all files whose names end with a tilde (~), which is used by many text editors such as Emacs to mark temporary files. You may also include a log, tmp, or pid directory; automatically generated documentation; and so on. Setting up a .gitignore file before you get going is generally a good idea so you don’t accidentally commit files that you really don’t want in your Git repository.
The rules for the patterns you can put in the .gitignore file are as follows:
Blank lines or lines starting with # are ignored.
Standard glob patterns work.
You can start patterns with a forward slash (/) to avoid recursivity.
You can end patterns with a forward slash (/) to specify a directory.
You can negate a pattern by starting it with an exclamation point (!).

Committing Your Changes

Now that your staging area is set up the way you want it, you can commit your changes. Remember that anything that is still unstaged – any files you have created or modified that you haven’t run git add on since you edited them – won’t go into this commit. They will stay as modified files on your disk. In this case, let’s say that the last time you ran git status, you saw that everything was staged, so you’re ready to commit your changes. The simplest way to commit is to type git commit:

$ git commit

Doing so launches your editor of choice. (This is set by your shell’s $EDITOR environment variable – usually vim or emacs, although you can configure it with whatever you want using the git config --global core.editor command as you saw in Getting Started).
The editor displays the following text (this example is a Vim screen):

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
# new file:   README
# modified:   CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C

You can see that the default commit message contains the latest output of the git status command commented out and one empty line on top. You can remove these comments and type your commit message, or you can leave them there to help you remember what you’re committing. (For an even more explicit reminder of what you’ve modified, you can pass the -v option to git commit. Doing so also puts the diff of your change in the editor so you can see exactly what changes you’re committing.) When you exit the editor, Git creates your commit with that commit message (with the comments and diff stripped out).
Alternatively, you can type your commit message inline with the commit command by specifying it after a -m flag, like this:

$ git commit -m "Story 182: Fix benchmarks for speed"
[master 463dc4f] Story 182: Fix benchmarks for speed
 2 files changed, 2 insertions(+)
 create mode 100644 README

Now you’ve created your first commit! You can see that the commit has given you some output about itself: which branch you committed to (master), what SHA-1 checksum the commit has (463dc4f), how many files were changed, and statistics about lines added and removed in the commit.

Remember that the commit records the snapshot you set up in your staging area. Anything you didn’t stage is still sitting there modified; you can do another commit to add it to your history. Every time you perform a commit, you’re recording a snapshot of your project that you can revert to or compare to later.

Skipping the Staging Area 
Although it can be amazingly useful for crafting commits exactly how you want them, the staging area is sometimes a bit more complex than you need in your workflow. If you want to skip the staging area, Git provides a simple shortcut. Adding the -a option to the git commit command makes Git automatically stage every file that is already tracked before doing the commit, letting you skip the git add part:

$ git status
On branch master
Your branch is up-to-date with 'origin/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:   CONTRIBUTING.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
 1 file changed, 5 insertions(+), 0 deletions(-)

Notice how you don’t have to run git add on the CONTRIBUTING.md file in this case before you commit. That’s because the -a flag includes all changed files. This is convenient, but be careful; sometimes this flag will cause you to include unwanted changes.

Removing Files

To remove a file from Git, you have to remove it from your tracked files (more accurately, remove it from your staging area) and then commit. The git rm command does that, and also removes the file from your working directory so you don’t see it as an untracked file the next time around.
If you simply remove the file from your working directory, it shows up under the “Changed but not updated” (that is, unstaged) area of your git status output:

$ rm PROJECTS.md

$ git status
On branch master

Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        deleted:    PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")
Then, if you run git rm, it stages the file’s removal:

$ git rm PROJECTS.md
rm 'PROJECTS.md'

$ git status

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    PROJECTS.md

Viewing the Commit History

After you have created several commits, or if you have cloned a repository with an existing commit history, you’ll probably want to look back to see what has happened. The most basic and powerful tool to do this is the git log command.

These examples use a very simple project called “simplegit”. To get the project, run

$ git clone https://github.com/schacon/simplegit-progit

When you run git log in this project, you should get output that looks something like this:

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit

By default, with no arguments, git log lists the commits made in that repository in reverse chronological order – that is, the most recent commits show up first. As you can see, this command lists each commit with its SHA-1 checksum, the author’s name and email, the date written, and the commit message.
A huge number and variety of options to the git log command are available to show you exactly what you’re looking for. Here, we’ll show you some of the most popular.
One of the more helpful options is -p, which shows the difference introduced in each commit. You can also use -2, which limits the output to only the last two entries:

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.platform  =   Gem::Platform::RUBY
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com"
     s.summary   =   "A simple gem for using Git in Ruby code."

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end
\ No newline at end of file

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    changed the version number

 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test

 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    first commit

 README           |  6 ++++++
 Rakefile         | 23 +++++++++++++++++++++++
 lib/simplegit.rb | 25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

Pushing

When you want to share a branch with the world, you need to push it up to a remote that you have write access to. Your local branches aren’t automatically synchronized to the remotes you write to – you have to explicitly push the branches you want to share. That way, you can use private branches for work you don’t want to share, and push up only the topic branches you want to collaborate on.
If you have a branch named serverfix that you want to work on with others, you can push it up the same way you pushed your first branch. Run git push <remote> <branch>:

$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      serverfix -> serverfix

This is a bit of a shortcut. Git automatically expands the serverfix branchname out to refs/heads/serverfix:refs/heads/serverfix, which means, “Take my serverfix local branch and push it to update the remote’s serverfix branch.” We’ll go over the refs/heads/ part in detail in Git Internals, but you can generally leave it off. You can also do git push origin serverfix:serverfix, which does the same thing – it says, “Take my serverfix and make it the remote’s serverfix.” You can use this format to push a local branch into a remote branch that is named differently. If you didn’t want it to be called serverfix on the remote, you could instead run git push origin serverfix:awesomebranchto push your local serverfix branch to the awesomebranch branch on the remote project.

The next time one of your collaborators fetches from the server, they will get a reference to where the server’s version of serverfix is under the remote branch origin/serverfix:

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

It’s important to note that when you do a fetch that brings down new remote-tracking branches, you don’t automatically have local, editable copies of them. In other words, in this case, you don’t have a new serverfix branch – you only have an origin/serverfix pointer that you can’t modify.
To merge this work into your current working branch, you can run git merge origin/serverfix. If you want your own serverfix branch that you can work on, you can base it off your remote-tracking branch:

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

Tracking Branches

Checking out a local branch from a remote-tracking branch automatically creates what is called a “tracking branch” (and the branch it tracks is called an “upstream branch”). Tracking branches are local branches that have a direct relationship to a remote branch. If you’re on a tracking branch and type git pull, Git automatically knows which server to fetch from and branch to merge into.
When you clone a repository, it generally automatically creates a master branch that tracks origin/master. However, you can set up other tracking branches if you wish – ones that track branches on other remotes, or don’t track the master branch. The simple case is the example you just saw, running git checkout -b [branch] [remotename]/[branch]. This is a common enough operation that Git provides the --track shorthand:

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

In fact, this is so common that there’s even a shortcut for that shortcut. If the branch name you’re trying to checkout (a) doesn’t exist and (b) exactly matches a name on only one remote, Git will create a tracking branch for you:

$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'

Pulling

While the git fetch command will fetch down all the changes on the server that you don’t have yet, it will not modify your working directory at all. It will simply get the data for you and let you merge it yourself. However, there is a command called git pull which is essentially a git fetch immediately followed by a git merge in most cases. If you have a tracking branch set up as demonstrated in the last section, either by explicitly setting it or by having it created for you by the clone or checkout commands, git pull will look up what server and branch your current branch is tracking, fetch from that server and then try to merge in that remote branch.
Generally it’s better to simply use the fetch and merge commands explicitly as the magic of git pullcan often be confusing.

Deleting Remote Branches

Suppose you’re done with a remote branch – say you and your collaborators are finished with a feature and have merged it into your remote’s master branch (or whatever branch your stable codeline is in). You can delete a remote branch using the --delete option to git push. If you want to delete your serverfix branch from the server, you run the following:

$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
 - [deleted]         serverfix

Basically all this does is remove the pointer from the server. The Git server will generally keep the data there for a while until a garbage collection runs, so if it was accidentally deleted, it’s often easy to recover.


The Protocols

Git can use four major protocols to transfer data: Local, HTTP, Secure Shell (SSH) and Git. Here we’ll discuss what they are and in what basic circumstances you would want (or not want) to use them.

Local Protocol

The most basic is the Local protocol, in which the remote repository is in another directory on disk. This is often used if everyone on your team has access to a shared filesystem such as an NFS mount, or in the less likely case that everyone logs in to the same computer. The latter wouldn’t be ideal, because all your code repository instances would reside on the same computer, making a catastrophic loss much more likely.
If you have a shared mounted filesystem, then you can clone, push to, and pull from a local file-based repository. To clone a repository like this or to add one as a remote to an existing project, use the path to the repository as the URL. For example, to clone a local repository, you can run something like this:

$ git clone /srv/git/project.git
Or you can do this:
$ git clone file:///srv/git/project.git

Generating Your SSH Public Key

That being said, many Git servers authenticate using SSH public keys. In order to provide a public key, each user in your system must generate one if they don’t already have one. This process is similar across all operating systems. First, you should check to make sure you don’t already have a key. By default, a user’s SSH keys are stored in that user’s ~/.ssh directory. You can easily check to see if you have a key already by going to that directory and listing the contents:

$ cd ~/.ssh
$ ls
authorized_keys2  id_dsa       known_hosts
config            id_dsa.pub

You’re looking for a pair of files named something like id_dsa or id_rsa and a matching file with a .pubextension. The .pub file is your public key, and the other file is your private key. If you don’t have these files (or you don’t even have a .ssh directory), you can create them by running a program called ssh-keygen, which is provided with the SSH package on Linux/Mac systems and comes with Git for Windows:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/schacon/.ssh/id_rsa):
Created directory '/home/schacon/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/schacon/.ssh/id_rsa.
Your public key has been saved in /home/schacon/.ssh/id_rsa.pub.
The key fingerprint is:
d0:82:24:8e:d7:f1:bb:9b:33:53:96:93:49:da:9b:e3 schacon@mylaptop.local

First it confirms where you want to save the key (.ssh/id_rsa), and then it asks twice for a passphrase, which you can leave empty if you don’t want to type a password when you use the key.

Now, each user that does this has to send their public key to you or whoever is administrating the Git server (assuming you’re using an SSH server setup that requires public keys). All they have to do is copy the contents of the .pub file and email it. The public keys look something like this:

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q== schacon@mylaptop.local

For a more in-depth tutorial on creating an SSH key on multiple operating systems, see the GitHub guide on SSH keys at https://help.github.com/articles/generating-ssh-keys.


Setting Up the Server

Let’s walk through setting up SSH access on the server side. In this example, you’ll use the authorized_keys method for authenticating your users. We also assume you’re running a standard Linux distribution like Ubuntu. First, you create a git user and a .ssh directory for that user.

$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys

Next, you need to add some developer SSH public keys to the authorized_keys file for the git user. Let’s assume you have some trusted public keys and have saved them to temporary files. Again, the public keys look something like this:

$ cat /tmp/id_rsa.john.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4L
ojG6rs6hPB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4k
Yjh6541NYsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9EzSdfd8AcCIicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myivO7TCUSBdLQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPqdAv8JggJICUvax2T9va5 gsg-keypair

You just append them to the git user’s authorized_keys file in its .ssh directory:

$ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys
$ cat /tmp/id_rsa.josie.pub >> ~/.ssh/authorized_keys
$ cat /tmp/id_rsa.jessica.pub >> ~/.ssh/authorized_keys

Account Setup and Configuration

The first thing you need to do is set up a free user account. Simply visit https://github.com, choose a user name that isn’t already taken, provide an email address and a password, and click the big green “Sign up for GitHub” button.


SSH Access

As of right now, you’re fully able to connect with Git repositories using the https:// protocol, authenticating with the username and password you just set up. However, to simply clone public projects, you don’t even need to sign up - the account we just created comes into play when we fork projects and push to our forks a bit later.
If you’d like to use SSH remotes, you’ll need to configure a public key. (If you don’t already have one, see Generating Your SSH Public Key.) Open up your account settings using the link at the top-right of the window:



From there, click the "Add an SSH key" button, give your key a name, paste the contents of your ~/.ssh/id_rsa.pub (or whatever you named it) public-key file into the text area, and click “Add key”.


0 comments:

Post a Comment