Softpanorama
May the source be with you, but remember the KISS principle ;-)

Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Git

Git's primitives are not inherently a source code management (SCM) system. As Torvalds explains,

In many ways you can just see git as a filesystem – it's content-addressable, and it has a notion of versioning, but I really really designed it coming at the problem from the viewpoint of a filesystem person (hey, kernels is what I do), and I actually have absolutely zero interest in creating a traditional SCM system.

The Eclipse Foundation reported in its annual community survey that as of May 2014, Git is now the most widely used source code management tool, with 42.9% of professional software developers reporting that they use Git as their primary source control system compared with 36.3% in 2013, 32% in 2012; or for Git responses excluding use of GitHub: 33.3% in 2014, 30.3% in 2013, 27.6% in 2012 and 12.8% in 2011. Open source directory Black Duck Open Hub reports a similar uptake among open source projects.

You’ll encounter several terms when reading about GIT:

 

Initializing a Repository in an Existing Directory

You can create 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.

If you’re starting to track an existing project in Git, you need to go to the project’s directory and type

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. 

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 add commands that specify the files you want to track, followed by a git commit:

$ git add *.py
$ 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.

Cloning an Existing Repository

If you want to get a copy of an existing Git repository – for example, a project you’d like to contribute to – the command you need is git clone. If you’re familiar with other VCS systems such as Subversion, you’ll notice that the command is “clone” and not “checkout”. This is an important distinction – instead of getting just a working copy, Git receives a full copy of nearly all data that the server has. Every version of every file for the history of the project is pulled down by default when you run git clone. In fact, if your server disk gets corrupted, you can often use nearly any of the clones on any client to set the server back to the state it was in when it was cloned (you may lose some server-side hooks and such, but all the versioned data would be there

You clone a repository with git clone [url]. For example, if you want to clone the Git linkable library called libgit2, you can do so like this:

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

That creates a directory named “libgit2”, initializes a .git directory inside it, pulls down all the data for that repository, and checks out a working copy of the latest version. If you go into the new libgit2 directory, you’ll see the project files in there, ready to be worked on or used. If you want to clone the repository into a directory named something other than “libgit2”, you can specify that as the next command-line option:

$ git clone https://github.com/libgit2/libgit2 mylibgit

That command does the same thing as the previous one, but the target directory is called mylibgit.

Git has a number of different transfer protocols you can use. The previous example uses the https:// protocol, but you may also see git:// or user@server:path/to/repo.git, which uses the SSH transfer protocol.

Getting Help

If you ever need help while using Git, there are three ways to get the manual page (manpage) help for any of the Git commands:

$ 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

These commands are nice because you can access them anywhere, even offline. If the manpages and this book aren’t enough and you need in-person help, you can try the #git or #github channel on the Freenode IRC server (irc.freenode.net). These channels are regularly filled with hundreds of people who are all very knowledgeable about Git and are often willing to help.

Checking Your Settings

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
...vi 

You may see keys more than once, because Git reads the same key from different files (/etc/gitconfig and ~/.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

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:

  1. /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.
  2. ~/.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.
  3. 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 root, which is wherever you decide to install Git on your Windows system when you run the installer. If you are using Git for Windows 2.x or later, 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.

Your Identity

The first thing you should do when you install Git is to set your user name and email address. This is important because every Git commit uses this information, and it’s immutably baked into the commits you start creating:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.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, which is system dependant.

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"
Note

Vim, Emacs and Notepad++ are popular text editors often used by developers on Unix based systems like Linux and OS X or a Windows system. If you are not familiar with either of these editors, you may need to search for specific instructions for how to set up your favorite editor with Git.

Warning

You may find, if you don’t setup an editor like this, you will likely get into a really confusing state when they are launched. Such example on a Windows system may include a prematurely terminated Git operation during a Git initiated edit.

Checking Your Settings

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/gitconfig and ~/.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

 


Top updates

Softpanorama Switchboard
Softpanorama Search


NEWS CONTENTS

Old News ;-)

[Mar 20, 2017] Git for Subversion users, Part 1 Getting started

Notable quotes:
"... The Wonderful Monkey Of Wittgenstein ..."
"... local ..."
"... branching ..."
"... automated regression test ..."
Mar 20, 2017 | www.ibm.com
Getting started

Git gets demystified for Subversion version control system users

photo- teodor zlatanov Teodor Zlatanov
Published on August 04, 2009 Share this page

Facebook Twitter Linked In Google+ E-mail this page Comments 3

For anyone unfamiliar with free and open source version control systems (VCSs), Subversion has become the standard non-commercial VCS, replacing the old champ, Concurrent Versions System (CVS). CVS is still just fine for limited use, but Subversion's allure is that it requires only a little bit of setup on a Web server and not much beyond that. Subversion does have some issues, which I'll discuss here, but for the most part, it just works.

So, why do we need another one? Git (capital "G"; git is the command-line tool) is in many ways designed to be better than Subversion. It is one of many distributed VCSs. My own first experience with these was with Arch/tla, as well as Mercurial, Bazaar, darcs, and a few others. For many reasons, which I'll discuss as far as they are relevant, Git has become popular and is often considered together with Subversion as the two leading choices for a personal or corporate VCS.

There are two important reasons to be interested in Git if you are a Subversion user.

  • You are looking to move to Git because Subversion is limiting you in some way.
  • You are curious about Git and want to find out how it compares to Subversion.

Well, perhaps there's a third reason: Git is a relatively hot technology you want to include on your resume. I hope that's not your primary goal; learning about Git is one of the most rewarding things a developer can do. Even if you don't use Git now, the concepts and workflow embodied in this distributed VCS are certain to be crucial knowledge for most segments of the IT industry in the next 10 years as the industry undergoes massive changes in scope and geographical distribution.

Finally, though it might not be a compelling reason if you're not a Linux kernel developer, the kernel and a number of other important projects are maintained using Git, so you'll want to be familiar with it if you plan to contribute.

This article is intended for beginning-to-intermediate Subversion users. It requires beginner-level knowledge of Subversion and some general knowledge of version control systems. The information here is mainly for users of UNIX®-like (Linux® and Mac OS X) systems, with a little bit thrown in for Windows® users.

Part 2 of this series will discuss more advanced uses of Git: merging branches, generating diffs, and other common tasks.

Subversion and Git basics

Henceforth, I'll abbreviate "Subversion" as "SVN" to save wear and tear on my U, B, E, R, S, I, and O keys.

git-svn

You may have heard of git-svn , a tool that lets you use Git against a Subversion repository. Though useful in some situations, being halfway distributed and using a centralized VCS is not the same as switching to a distributed VCS.

So, what's SVN good for? You might already know this, but a VCS is not about files; it's about changes. SVN, running on a central server, adds changes to its repository of data and can give you a snapshot after every change. That snapshot has a revision number; the revision number is very important to SVN and the people who use it. If your change goes in after mine, you're guaranteed to have a higher revision number.

Git has a similar goal-tracking changes-but has no centralized server. This difference is crucial. Where SVN is centralized, Git is distributed; therefore, Git has no way to provide an increasing revision number, because there is no "latest revision." It still has unique revision IDs; they are just not as useful on their own as the SVN revision numbers.

With Git, the crucial action is no longer the commit ; it is the merge . Anyone can clone a repository and commit to the clone. The owner of the repository is given the choice of merging changes back. Alternatively, developers can push changes back to the repository. I'll explore only the latter, authorized-push model.

Keeping a directory under SVN

Let's start with a simple common example: tracking a directory's contents with SVN. You'll need a SVN server and, obviously, a directory of files, as well as an account on that server with commit rights for at least one path. Get started by adding and committing the directory:

Listing 1. Setting up a directory under SVN
1 2 3 4 5 % svn co http://svnserver/...some path here.../top % cd top % cp -r ~/my_directory . % svn add my_directory % svn commit -m 'added directory'

What does this let you do? Now you can get the latest version of any file committed under this directory, delete files, rename them, create new files or directories, commit changes to existing files, and more:

Listing 2. Basic file operations under SVN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # get latest % svn up # what's the status? % svn st # delete files % svn delete # rename files (really a delete + add that keeps history) % svn rename # make directory % svn mkdir # add file % svn add # commit changes (everything above, plus any content changes) % svn commit

I won't examine these commands in detail here, but do keep them in mind. For help on any of these commands, just type svn help COMMAND , and Subversion will show you some basic help; go to the manual for more.

Keeping a directory under Git

I'll follow the same path as I did with the SVN example. As before, I'm assuming you already have a directory full of data.

For the remote server, I'll use the free github.com service, but, of course, you can set up your own server if you like. GitHub is an easy way to play with a remote Git repository. As of this writing, for a free account you're limited to 300MB of data and your repository must be public. I signed up as user "tzz" and created a public repository called "datatest"; feel free to use it. I gave my public SSH key; you should generate one if you don't have one already. You may also want to try the Gitorious server or repo.or.cz. You'll find a long list of Git hosting services on the git.or.cz Wiki (see Related topics for a link).

One nice thing about GitHub is that it's friendly. It tells you exactly what commands are needed to set up Git and initialize the repository. I'll walk through those with you.

First, you need to install Git, which is different on every platform, and then initialize it. The Git download page (see Related topics ) lists a number of options depending on platform. (On Mac OS X, I used the port install git-core command, but you need to set up MacPorts first. There's also a standalone MacOS X Git installer linked from the Git download page; that will probably work better for most people.)

Once you have it installed, here are the commands I used for a basic setup (pick your own user name and e-mail address, naturally):

Listing 3. Basic Git setup
1 2 % git config --global user.name "Ted Zlatanov" % git config --global user.email "tzz@bu.edu"

Already you might see a difference from SVN; there, your user identity was server-side and you were whomever the server said you were. In Git, you can be The Wonderful Monkey Of Wittgenstein if you want (I resisted the temptation).

Next, I set up the data files and initialize my repository with them. (GitHub will also import from a public SVN repository, which can be helpful.)

Listing 4. Directory setup and first commit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # grab some files % cp -rp ~/.gdbinit gdbinit % mkdir fortunes % cp -rp ~/.fortunes.db fortunes/data.txt # initialize % git init # "Initialized empty Git repository in /Users/tzz/datatest/.git/" # add the file and the directory % git add gdbinit fortunes % git commit -m 'initializing' #[master (root-commit) b238ddc] initializing # 2 files changed, 2371 insertions(+), 0 deletions(-) # create mode 100644 fortunes/data.txt # create mode 100644 gdbinit

In the output above, Git is telling us about file modes; 100644 refers to the octal version of the permission bits on those files. You don't need to worry about that, but the 2371 insertions is puzzling. It only changed two files, right? That number actually refers to the number of lines inserted. We didn't delete any, of course.

How about pushing our new changes to the GitHub server? The docs tell us how to add a remote server called "origin" (you can use any name). I should mention here that if you want to learn more about any Git command, for example, git remote , you'd type git remote --help or git help remote . This is typical for command-line tools, and SVN does something very similar.

Listing 5. Push the changes to the remote
1 2 3 4 5 6 7 8 9 10 11 12 # remember the remote repository is called "datatest"? % git remote add origin git@github.com:tzz/datatest.git # push the changes % git push origin master #Warning: Permanently added 'github.com,65.74.177.129' (RSA) to the list of known hosts. #Counting objects: 5, done. #Delta compression using 2 threads. #Compressing objects: 100% (4/4), done. #Writing objects: 100% (5/5), 29.88 KiB, done. #Total 5 (delta 0), reused 0 (delta 0) #To git@github.com:tzz/datatest.git # * [new branch] master -> master

The warning is from OpenSSH because github.com was not a known host before. Nothing to worry about.

Git messages are, shall we say, thorough . Unlike SVN's messages, which are easy to understand, Git is written for mentats, by mentats. If you're from Frank Herbert's Dune universe and are trained as a human computer, you've probably already written your own version of Git, just because you can. For the rest of us, delta compression and the number of threads used by it are just not very relevant (and they make our heads hurt).

The push was done over SSH, but you can use other protocols, such as HTTP, HTTPS, rsync, and file. See git push --help .

Here is the crucial, most important, basic difference between SVN and Git. SVN's commit says "push this to the central server." Until you commit in SVN, your changes are ethereal. With Git, your commit is local , and you have a local repository no matter what happens on the remote side. You can back out a change, branch, commit to the branch, and so on without any interaction with the remote server. Pushing with Git is effectively a synchronization of your repository's state with the remote server.

All right, so finally let's see the Git log of what just happened:

Listing 6. The Git log
1 2 3 4 5 6 % git log #commit b238ddca99ee582e1a184658405e2a825f0815da #Author: Ted Zlatanov <tzz@lifelogs.com> #Date: ...commit date here... # # initializing

Only the commit is in the log (note the long, random-looking commit ID as opposed to the SVN revision number). There is no mention of the synchronization via git push .

Collaborating through Git

So far we've been using Git as a SVN replacement. Of course, to make it interesting, we have to get multiple users and changesets involved. I'll check out the repository to another machine (running Ubuntu GNU/Linux in this case; you'll need to install git-core and not git ):

Listing 7. Setting up another Git identity and checking out the repository
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 % git config --global user.name "The Other Ted" % git config --global user.email "tzz@bu.edu" % git clone git@github.com:tzz/datatest.git #Initialized empty Git repository in /home/tzz/datatest/.git/ #Warning: Permanently added 'github.com,65.74.177.129' (RSA) to the list of known hosts. #remote: Counting objects: 5, done. #remote: Compressing objects: 100% (4/4), done. #Indexing 5 objects... #remote: Total 5 (delta 0), reused 0 (delta 0) # 100% (5/5) done % ls datatest #fortunes gdbinit % ls -a datatest/.git # . .. branches config description HEAD hooks index info logs objects refs % ls -a datatest/.git/hooks # . .. applypatch-msg commit-msg post-commit post-receive post-update # pre-applypatch pre-commit pre-rebase update

Again, notice the OpenSSH warning indicating we have not done business with GitHub over SSH before from this machine. The git clone command is like a SVN checkout, but instead of getting a synthesized version of the contents (a snapshot as of a particular revision, or the latest revision), you are getting the whole repository.

I included the contents of the datatest/.git directory and the hooks subdirectory under it to show that you really do get everything. Git keeps no secrets by default, unlike SVN, which keeps the repository private by default and only allows access to snapshots.

Incidentally, if you want to enforce some rules on your Git repository, whether on every commit or at other times, the hooks are the place. They are shell scripts, much like the SVN hooks, and have the same "return zero for success, anything else for failure" standard UNIX convention. I won't go into more detail on hooks here, but if your ambition is to use Git in a team, you should definitely read up on them.

All right, so "The Other Ted" is frisky and wants to add a new file in the master branch (roughly equivalent to SVN's TRUNK) and also make a new branch with some changes to the gdbinit file.

Listing 8. Adding a file and making a new branch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 # get a file to add... % cp ~/bin/encode.pl . % git add encode.pl % git commit -m 'adding encode.pl' #Created commit 6750342: adding encode.pl # 1 files changed, 1 insertions(+), 0 deletions(-) # create mode 100644 encode.pl % git log #commit 675034202629e5497ed10b319a9ba42fc72b33e9 #Author: The Other Ted <tzz@bu.edu> #Date: ...commit date here... # # adding encode.pl # #commit b238ddca99ee582e1a184658405e2a825f0815da #Author: Ted Zlatanov <tzz@lifelogs.com> #Date: ...commit date here... # # initializing % git branch empty-gdbinit % git branch # empty-gdbinit #* master % git checkout empty-gdbinit #Switched to branch "empty-gdbinit" % git branch #* empty-gdbinit # master % git add gdbinit % git commit -m 'empty gdbinit' #Created commit 5512d0a: empty gdbinit # 1 files changed, 0 insertions(+), 1005 deletions(-) % git push #updating 'refs/heads/master' # from b238ddca99ee582e1a184658405e2a825f0815da # to 675034202629e5497ed10b319a9ba42fc72b33e9 #Generating pack... #Done counting 4 objects. #Result has 3 objects. #Deltifying 3 objects... # 100% (3/3) done #Writing 3 objects... # 100% (3/3) done #Total 3 (delta 0), reused 0 (delta 0)

That was a long example and I hope you didn't fall asleep; if you did, I hope you dreamt of Git repositories synchronizing in an endless waltz of changesets. (Oh, you'll have those dreams, don't worry.)

First, I added a file (encode.pl, only one line) and committed it. After the commit, the remote repository at GitHub did not have any idea I had made changes. I then made a new branch called empty-gdbinit and switched to it (I could have done this with git checkout -b empty-gdbinit as well). In that branch, I emptied the gdbinit file and committed that change. Finally, I pushed to the remote server.

If I switch to the master branch, I won't see the empty gdbinit in the logs. So, each branch has its own log, which makes sense.

Listing 9. Looking at logs between branches
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 # we are still in the empty-gdbinit branch % git log #commit 5512d0a4327416c499dcb5f72c3f4f6a257d209f #Author: The Other Ted <tzz@bu.edu> #Date: ...commit date here... # # empty gdbinit # #commit 675034202629e5497ed10b319a9ba42fc72b33e9 #Author: The Other Ted <tzz@bu.edu> #Date: ...commit date here... # # adding encode.pl # #commit b238ddca99ee582e1a184658405e2a825f0815da #Author: Ted Zlatanov <tzz@lifelogs.com> #Date: ...commit date here... # # initializing % git checkout master #Switched to branch "master" % git log #commit 675034202629e5497ed10b319a9ba42fc72b33e9 #Author: The Other Ted <tzz@bu.edu> #Date: ...commit date here... # # adding encode.pl # #commit b238ddca99ee582e1a184658405e2a825f0815da #Author: Ted Zlatanov <tzz@lifelogs.com> #Date: ...commit date here... # # initializing

When I did the push, Git said, "Hey, look at that, a new file called encode.pl" on GitHub's servers.

GitHub's Web interface will now display encode.pl. But there's still only one branch on GitHub. Why was the empty-gdbinit branch not synchronized? It's because Git doesn't assume you want to push branches and their changes by default. For that, you need to push everything:

Listing 10. Pushing all
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 % git push -a #updating 'refs/heads/empty-gdbinit' # from 0000000000000000000000000000000000000000 # to 5512d0a4327416c499dcb5f72c3f4f6a257d209f #updating 'refs/remotes/origin/HEAD' # from 0000000000000000000000000000000000000000 # to b238ddca99ee582e1a184658405e2a825f0815da #updating 'refs/remotes/origin/master' # from 0000000000000000000000000000000000000000 # to b238ddca99ee582e1a184658405e2a825f0815da #Generating pack... #Done counting 5 objects. #Result has 3 objects. #Deltifying 3 objects... # 100% (3/3) done #Writing 3 objects... # 100% (3/3) done #Total 3 (delta 1), reused 0 (delta 0)

Again, the mentat interface is here in full glory. But we can figure things out, right? We may not be mentats, but at least we have the common sense to figure that 0000000000000000000000000000000000000000 is some kind of special initial tag. We can also see from the logs in Listing 9 that tag 5512d0a4327416c499dcb5f72c3f4f6a257d209f is the last (and only) commit in the empty-gdbinit branch. The rest might as well be in Aramaic for most users; they just won't care. GitHub will now show the new branch and the changes in it.

You can use git mv and git rm to manage files, renaming and removing them, respectively.

Conclusion

In this article, I explained basic Git concepts and used Git to keep a simple directory's contents under version control, comparing Git with Subversion along the way. I explained branching using a simple example.

In Part 2, I will explore merging, generating diffs, and some of the other Git commands. I strongly encourage you to read the very understandable Git manual or at least go through the tutorial. It's all accessible from the Git home page, so please spend some time exploring it. (See the Related topics below for links.) From the perspective of a SVN user, you don't need much more.

On the other hand, Git is a very rich DVCS; learning more about its features will almost certainly lead to using them to simplify and improve your VCS workflow. Plus, you may even have a dream or two about Git repositories.

This is the second of a two-part series. You should read the Part 1 if you haven't already, as I'll use the same Git and Subversion (SVN) setup, and it will get you used to my sense of humor. Branching and merging in SVN

Easily the greatest source of headaches for version control system (VCS) managers are branching and merging . The vast majority of developers prefer to commit all of their changes in the trunk. As soon as branching and merging come up, developers start to complain, and the VCS manager gets to deal with it.

To be fair to developers, branching and merging are scary operations. The results are not always obvious, and merging can cause problems by undoing other people's work.

SVN manages the trunk well and many developers don't bother with branching. SVN clients before 1.5 were a bit primitive about tracking merges, so if you're used to older SVN clients, you might not know about SVN's svn:mergeinfo property.

There's also a tool called svnmerge.py (see Related topics for a link). svnmerge.py can track merges without the svn:mergeinfo support and thus works for older SVN clients.

Because of the complexity and variations in SVN's merge support, I won't provide specific examples. Instead, let's just talk about Git's branch merging. You can read the SVN manual referenced in the Related topics section if you are interested.

Branching and merging in Git

If Concurrent Versions System (CVS) is the village idiot when it comes to branching and merging, SVN is the vicar and Git is the mayor. Git was practically designed to support easy branching and merging. This Git feature not only impresses in the demo but is also handy every day.

To give you an example, Git has multiple merge strategies, including one called the octopus strategy, which allows you to merge multiple branches at once. An octopus strategy! Just think about the insanity of attempting to do this kind of merge in CVS or SVN. Git also supports a different kind of merging called rebasing . I won't examine rebasing here, but it is quite helpful for simplifying the repository history, so you might want to look it up.

Before I proceed with the merge example below, you should be familiar with the branch setup in Part 1 . You have HEAD (the current branch, in this case master ) and the empty-gdbinit branch. First, let's merge empty-gdbinit into HEAD , then make a change in HEAD and merge it the other way into empty-gdbinit :

Listing 1. Merging changes from branch to HEAD with Git
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # start clean % git clone git@github.com:tzz/datatest.git # ...clone output... # what branches are available? % git branch -a #* master # origin/HEAD # origin/empty-gdbinit # origin/master # do the merge % git merge origin/empty-gdbinit #Updating 6750342..5512d0a #Fast forward # gdbinit | 1005 --------------------------------------------------------------- # 1 files changed, 0 insertions(+), 1005 deletions(-) # now push the merge to the server % git push #Total 0 (delta 0), reused 0 (delta 0) #To git@github.com:tzz/datatest.git # 6750342..5512d0a master -> master

This is not hard as long as you realize that master has HEAD , and after the merge with the empty-gdbinit branch, the master branch gets pushed to the remote server to synchronize with origin/master . In other words, you merged locally from a remote branch and then pushed the result to another remote branch.

What's important here is to see how Git does not care which branch is authoritative. You can merge from a local branch to another local branch or to a remote branch. The Git server only gets involved for remote operations. In contrast, SVN always requires the SVN server, because with SVN the repository on the server is the only authoritative version.

Of course, Git is a distributed VCS, so none of this is surprising. It was designed to work without central authority. Still, the freedom can be a bit jarring to developers used to CVS and SVN.

Now, properly prepared with all this grand talk, let's make another local branch:

Listing 2. Creating and switching to a release branch on machine A
1 2 3 4 5 6 7 8 9 10 11 # create and switch to the stable branch % git checkout -b release-stable #Switched to a new branch "release-stable" % git branch # master #* release-stable # push the new branch to the origin % git push --all #Total 0 (delta 0), reused 0 (delta 0) #To git@github.com:tzz/datatest.git # * [new branch] release-stable -> release-stable

Now, on a different machine we will remove the gdbinit file from the master branch. Of course, it doesn't have to be a different machine, it can simply be in a different directory, but I'm reusing "The Other Ted" identity on Ubuntu from Part 1 for machine B.

Listing 3. Removing gdbinit from master branch on machine B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # start clean % git clone git@github.com:tzz/datatest.git # ...clone output... % git rm gdbinit # rm 'gdbinit' # hey, what branch am I in? % git branch #* master # all right, commit my changes % git commit -m "removed gdbinit" #Created commit 259e0fd: removed gdbinit # 1 files changed, 0 insertions(+), 1 deletions(-) # delete mode 100644 gdbinit # and now push the change to the remote branch % git push #updating 'refs/heads/master' # from 5512d0a4327416c499dcb5f72c3f4f6a257d209f # to 259e0fda9a8e9f3b0a4b3019781b99a914891150 #Generating pack... #Done counting 3 objects. #Result has 2 objects. #Deltifying 2 objects... # 100% (2/2) done #Writing 2 objects... # 100% (2/2) done #Total 2 (delta 1), reused 0 (delta 0)

Nothing crazy here (except for "deltifying," which sounds like something you'd do at the gym or something a river might do near a large body of water). But what happens on machine A in the release-stable branch?

Listing 4. Merging removal of gdbinit from master branch to release-stable branch on machine A
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # remember, we're in the release-stable branch % git branch # master #* release-stable # what's different vs. the master? % git diff origin/master #diff --git a/gdbinit b/gdbinit #new file mode 100644 #index 0000000..8b13789 #--- /dev/null #+++ b/gdbinit #@@ -0,0 +1 @@ #+ # pull in the changes (removal of gdbinit) % git pull origin master #From git@github.com:tzz/datatest # * branch master -> FETCH_HEAD #Updating 5512d0a..259e0fd #Fast forward # gdbinit | 1 - # 1 files changed, 0 insertions(+), 1 deletions(-) # delete mode 100644 gdbinit # push the changes to the remote server (updating the remote release-stable branch) % git push #Total 0 (delta 0), reused 0 (delta 0) #To git@github.com:tzz/datatest.git # 5512d0a..259e0fd release-stable -> release-stable

The mentat interface, which I referred to in Part 1 , strikes again in the diff. You're supposed to know that /dev/null is a special file that contains nothing, and thus the remote master branch has nothing, whereas the local release-stable branch has the gdbinit file. That's not always obvious to most users.

After all that fun, the pull merges the local branch with origin/master and then the push updates origin/release-stable with the changes. As usual, "delta" is the Git developer's favorite word-one never misses a chance to use it.

Bisecting changes

I won't go into the git bisect command in detail here, because it is quite complicated, but I wanted to mention it because it is a terrific tool. Bisecting changes is really a binary search across the commit log. "Binary" means that the search splits the search interval down the middle and tests the middle each time to decide if the wanted segment is above or below the middle.

The way it works is simple. You tell Git that version A is good and version Z is bad. Git then asks you (or asks an automated script) if the version halfway between A and Z, say Q, is bad. If Q is bad, then the bad commit is between A and Q; otherwise the bad commit is between Q and Z. The process is repeated until the bad commit is found.

It's especially nice that bisecting can be automated with a test script. That makes it possible to write a test for version Z and use it backwards to find when a feature broke, which most developers would call an automated regression test . Those will save you time.

Resolving conflicts

Merge conflicts are inevitable in any VCS and especially so in a distributed VCS such as Git. What happens if two people change a file in conflicting ways in the same branch? Both of the following examples are in the master branch of the datatest repository we've been using so far.

First we make a change to encode.pl on machine B:

Listing 5. "Does not work" on machine B
1 2 3 4 5 6 7 8 9 10 # we're at time T1 # change the contents % echo "# this script doesn't work" > encode.pl % git commit -a -m 'does not work' #Created commit e61713b: does not work # 1 files changed, 1 insertions(+), 1 deletions(-) # we're at time T2 now, what's our status? % git status # On branch master #nothing to commit (working directory clean)

Now we make a change to encode.pl on machine A without awareness of the changes on machine B, and push it:

Listing 6. "Does work" on machine A
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # we're at time T2 # change the contents % echo "this script does work" > encode.pl % git commit -a -m 'does not work' #Created commit e61713b: does not work # 1 files changed, 1 insertions(+), 1 deletions(-) # we're at time T3 now, what's our status? % git status # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # #nothing to commit (working directory clean) % git push #Counting objects: 5, done. #Delta compression using 2 threads. #Compressing objects: 100% (2/2), done. #Writing objects: 100% (3/3), 298 bytes, done. #Total 3 (delta 0), reused 0 (delta 0) #To git@github.com:tzz/datatest.git # 259e0fd..f949703 master -> master

Now, on machine B, we do a git pull and realize things are not so wonderful:

Listing 7. Uh-oh on machine B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 % git pull #remote: Counting objects: 5, done. #Compressing objects: 100% (2/2), done.) #remote: Total 3 (delta 0), reused 0 (delta 0) #Unpacking 3 objects... # 100% (3/3) done #* refs/remotes/origin/master: fast forward to branch 'master' # of git@github.com:tzz/datatest # old..new: 259e0fd..f949703 #Auto-merged encode.pl #CONFLICT (content): Merge conflict in encode.pl #Automatic merge failed; fix conflicts and then commit the result. # the next command is optional % echo uh-oh #uh-oh # you can also use "git diff" to see the conflicts % cat encode.pl #<<<<<<< HEAD:encode.pl ## this script doesn't work #======= #this script works #>>>>>>> f9497037ce14f87ff984c1391b6811507a4dd86c:encode.pl

This situation is very common in SVN as well. Someone else's changes disagree with your version of a file. Just edit the file and commit:

Listing 8. Fixing and committing on machine B
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # fix encode.pl before this to contain only "# this script doesn't work"... % echo "# this script doesn't work" > encode.pl # commit, conflict resolved % git commit -a -m '' #Created commit 05ecdf1: Merge branch 'master' of git@github.com:tzz/datatest % git push #updating 'refs/heads/master' # from f9497037ce14f87ff984c1391b6811507a4dd86c # to 05ecdf164f17cd416f356385ce8f5c491b40bf01 #updating 'refs/remotes/origin/HEAD' # from 5512d0a4327416c499dcb5f72c3f4f6a257d209f # to f9497037ce14f87ff984c1391b6811507a4dd86c #updating 'refs/remotes/origin/master' # from 5512d0a4327416c499dcb5f72c3f4f6a257d209f # to f9497037ce14f87ff984c1391b6811507a4dd86c #Generating pack... #Done counting 8 objects. #Result has 4 objects. #Deltifying 4 objects... # 100% (4/4) done #Writing 4 objects... # 100% (4/4) done #Total 4 (delta 0), reused 0 (delta 0)

That was easy, wasn't it? Let's see what happens on machine A next time it updates.

Listing 9. Fixing and committing on machine B
1 2 3 4 5 6 7 8 9 10 11 12 13 % git pull #remote: Counting objects: 8, done. #remote: Compressing objects: 100% (3/3), done. #remote: Total 4 (delta 0), reused 0 (delta 0) #Unpacking objects: 100% (4/4), done. #From git@github.com:tzz/datatest # f949703..05ecdf1 master -> origin/master #Updating f949703..05ecdf1 #Fast forward # encode.pl | 2 +- # 1 files changed, 1 insertions(+), 1 deletions(-) % cat encode.pl ## this script doesn't work

Fast forward means that the local branch caught up with the remote branch automatically, because it contained nothing new to the remote branch. In other words, a fast forward implies no merging was needed; all the local files were no newer than the remote branch's latest push.

Finally, I should mention git revert and git reset , which are very useful for undoing a commit or other changes to the Git tree. There's no room to explain them here, but make sure you know how to use them.

Conclusion

This article opened up the concept of merging, showing what it's like to keep the local and remote branches on two machines and resolving conflicts between them. I also drew attention to the complicated, even arcane Git messages, because compared with SVN, Git is much more verbose and much less intelligible. When you couple this fact with the complex syntax of Git's commands, it can make Git pretty intimidating for most beginners. However, once a few basic concepts are explained, Git gets much easier-even pleasant!


Downloadable resources
Related topics

Related topics

The Git - SVN Crash Course is a handy reference for those already familiar with SVN. Another good tutorial is Flavio Castelli's Howto use Git and SVN together .

[Feb 20, 2017] Git - Branches Atlassian Git Tutorial

Feb 20, 2017 | www.atlassian.com

git branch

A branch represents an independent line of development. Branches serve as an abstraction for the edit/stage/commit process discussed in Git Basics , the first module of this series. You can think of them as a way to request a brand new working directory, staging area, and project history. New commits are recorded in the history for the current branch, which results in a fork in the history of the project.

The git branch command lets you create, list, rename, and delete branches. It doesn't let you switch between branches or put a forked history back together again. For this reason, git branch is tightly integrated with the git checkout and git merge commands.

Usage
git branch

List all of the branches in your repository.

git branch <branch>

Create a new branch called <branch> . This does not check out the new branch.

git branch -d <branch>

Delete the specified branch. This is a "safe" operation in that Git prevents you from deleting the branch if it has unmerged changes.

git branch -D <branch>

Force delete the specified branch, even if it has unmerged changes. This is the command to use if you want to permanently throw away all of the commits associated with a particular line of development.

git branch -m <branch>

Rename the current branch to <branch> .

Discussion

In Git, branches are a part of your everyday development process. When you want to add a new feature or fix a bug-no matter how big or how small-you spawn a new branch to encapsulate your changes. This makes sure that unstable code is never committed to the main code base, and it gives you the chance to clean up your feature's history before merging it into the main branch.

Git Tutorial: git branch

For example, the diagram above visualizes a repository with two isolated lines of development, one for a little feature, and one for a longer-running feature. By developing them in branches, it's not only possible to work on both of them in parallel, but it also keeps the main master branch free from questionable code.

Branch Tips

The implementation behind Git branches is much more lightweight than SVN's model. Instead of copying files from directory to directory, Git stores a branch as a reference to a commit. In this sense, a branch represents the tip of a series of commits-it's not a container for commits. The history for a branch is extrapolated through the commit relationships.

This has a dramatic impact on Git's merging model. Whereas merges in SVN are done on a file-basis, Git lets you work on the more abstract level of commits. You can actually see merges in the project history as a joining of two independent commit histories.

Example Creating Branches

It's important to understand that branches are just pointers to commits. When you create a branch, all Git needs to do is create a new pointer-it doesn't change the repository in any other way. So, if you start with a repository that looks like this:

Git Tutorial: repository without any branches

Then, you create a branch using the following command:

git branch crazy-experiment

The repository history remains unchanged. All you get is a new pointer to the current commit:

Git Tutorial: Create new branch

Note that this only creates the new branch. To start adding commits to it, you need to select it with git checkout , and then use the standard git add and git commit commands. Please see the git checkout section of this module for more information.

Deleting Branches

Once you've finished working on a branch and have merged it into the main code base, you're free to delete the branch without losing any history:

git branch -d crazy-experiment

However, if the branch hasn't been merged, the above command will output an error message:

error: The branch 'crazy-experiment' is not fully merged. If you are sure you want to delete it, run 'git branch -D crazy-experiment'.

This protects you from losing your reference to those commits, which means you would effectively lose access to that entire line of development. If you really want to delete the branch (e.g., it's a failed experiment), you can use the capital -D flag:

git branch -D crazy-experiment

This deletes the branch regardless of its status and without warnings, so use it judiciously.

git checkout

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.

In the previous module , we saw how git checkout can be used to view old commits. Checking out branches is similar in that the working directory is updated to match the selected branch/revision; however, new changes are saved in the project history-that is, it's not a read-only operation.

Usage
git checkout <existing-branch>

Check out the specified branch, which should have already been created with git branch . This makes <existing-branch> the current branch, and updates the working directory to match.

git checkout -b <new-branch>

Create and check out <new-branch>. The -b option is a convenience flag that tells Git to run git branch <new-branch> before running git checkout <new-branch> . git checkout -b <new-branch> <existing-branch>

Same as the above invocation, but base the new branch off of <existing-branch> instead of the current branch.

Discussion

git checkout works hand-in-hand with git branch . When you want to start a new feature, you create a branch with git branch , then check it out with git checkout . You can work on multiple features in a single repository by switching between them with git checkout .

Git Tutorial: Switch between multiple features in a single repo with git checkout.

Having a dedicated branch for each new feature is a dramatic shift from the traditional SVN workflow. It makes it ridiculously easy to try new experiments without the fear of destroying existing functionality, and it makes it possible to work on many unrelated features at the same time. In addition, branches also facilitate several collaborative workflows.

Detached HEADs

Now that we've seen the three main uses of git checkout we can talk about that "detached HEAD " we encountered in the previous module.

Remember that the HEAD is Git's way of referring to the current snapshot. Internally, the git checkout command simply updates the HEAD to point to either the specified branch or commit. When it points to a branch, Git doesn't complain, but when you check out a commit, it switches into a "detached HEAD " state.

Git Tutorial: Attached vs Detached Head

This is a warning telling you that everything you're doing is "detached" from the rest of your project's development. If you were to start developing a feature while in a detached HEAD state, there would be no branch allowing you to get back to it. When you inevitably check out another branch (e.g., to merge your feature in), there would be no way to reference your feature:

Git Tutorial: Detached Head state

The point is, your development should always take place on a branch-never on a detached HEAD . This makes sure you always have a reference to your new commits. However, if you're just looking at an old commit, it doesn't really matter if you're in a detached HEAD state or not.

Example

The following example demonstrates the basic Git branching process. When you want to start working on a new feature, you create a dedicated branch and switch into it:

git branch new-feature git checkout new-feature

Then, you can commit new snapshots just like we've seen in previous modules:

# Edit some files git add <file> git commit -m "Started work on a new feature" # Repeat

All of these are recorded in new-feature , which is completely isolated from master . You can add as many commits here as necessary without worrying about what's going on in the rest of your branches. When it's time to get back to "official" code base, simply check out the master branch:

git checkout master

This shows you the state of the repository before you started your feature. From here, you have the option to merge in the completed feature, branch off a brand new, unrelated feature, or do some work with the stable version of your project.

[Feb 20, 2017] Git Behind the Curtain What Happens When You Commit, Branch, and Merge - DZone DevOps

Feb 20, 2017 | dzone.com
Discover how to optimize your DevOps workflows with our cloud-based automated testing infrastructure, brought to you in partnership with Sauce Labs .

This is the script for a talk that I gave at BarCamp Philly . The talk is a "live committing" exercise, and this post contains all the information needed to follow along, as well as some links to relevant source material and minus my pauses, typos, and attempts at humor.

Object Management

I think that the first thing to understand about Git is that it's not strictly a source control system; it's more like a versioned filesystem that happens to be good at source control. Traditionally, source control systems focused on the evolution of files. For example, RCS (and its successor CVS) maintain a separate file in the repository for each source file. These repository files hold the entire history of the file as a sequence of diffs that allow the tool to reconstruct any version. Subversion applies the idea of diffs to the entire repository, allowing it to track files as they move between directories.

Git takes a different approach. Rather than constructing the state of the repository via diffs, it maintains snapshots of the repository and constructs diffs from those (if you don't believe this, read on). This allows very efficient comparisons between any two points in history but does consume more disk space. I think the key insight is not just that disk is cheap and programmer time expensive, but that real-world software projects don't have a lot of large files, and those files don't experience a lot of churn.

To see Git in action, we'll create a temporary directory, initialize it as a repository, and create a couple of files. I should note here that I'm using bash on Linux; if you're running Windows you're on your own re commands. Anything that starts with " > " is a command that I typed; anything else is the response from the system.

... ... ...

So, what does it mean that git log produces the illusion of a series of merged commits? Consider what happens when you check out one of the commits in the list, for example 2e68e9b9 .

This was a commit that was made on the branch. If you check out that commit and look at the commit log from that point, you'll see that commit 5269b074 no longer appears. It was made on master , in a completely different chain of commits.

In a complex series of merges (say, multiple development branches onto an integration branch and several integration branches onto a feature branch) you can completely lose track of where and why a change was made. If you try to diff your way through the commit history, you'll find that the code changes dramatically between commits, and appears to flip-flop. You're simply seeing the code state on different branches.

[Sep 13, 2016] Saving changes Atlassian Git Tutorial

Notable quotes:
"... entire contents ..."
Sep 13, 2016 | www.atlassian.com

The git add command adds a change in the working directory to the staging area. It tells Git that you want to include updates to a particular file in the next commit. However, git add doesn't really affect the repository in any significant way-changes are not actually recorded until you run git commit .

In conjunction with these commands, you'll also need git status to view the state of the working directory and the staging area.

Usage

git add <file>

Stage all changes in <file> for the next commit.

git add <directory>

Stage all changes in <directory> for the next commit.

git add -p

Begin an interactive staging session that lets you choose portions of a file to add to the next commit. This will present you with a chunk of changes and prompt you for a command. Use y to stage the chunk, n to ignore the chunk, s to split it into smaller chunks, e to manually edit the chunk, and q to exit.

Discussion

The git add and git commit commands compose the fundamental Git workflow. These are the two commands that every Git user needs to understand, regardless of their team's collaboration model. They are the means to record versions of a project into the repository's history.

Developing a project revolves around the basic edit/stage/commit pattern. First, you edit your files in the working directory. When you're ready to save a copy of the current state of the project, you stage changes with git add . After you're happy with the staged snapshot, you commit it to the project history with git commit .

The git add command should not be confused with svn add , which adds a file to the repository. Instead, git add works on the more abstract level of changes . This means that git add needs to be called every time you alter a file, whereas svn add only needs to be called once for each file. It may sound redundant, but this workflow makes it much easier to keep a project organized.

The Staging Area

The staging area is one of Git's more unique features, and it can take some time to wrap your head around it if you're coming from an SVN (or even a Mercurial) background. It helps to think of it as a buffer between the working directory and the project history.

Instead of committing all of the changes you've made since the last commit, the stage lets you group related changes into highly focused snapshots before actually committing it to the project history. This means you can make all sorts of edits to unrelated files, then go back and split them up into logical commits by adding related changes to the stage and commit them piece-by-piece. As in any revision control system, it's important to create atomic commits so that it's easy to track down bugs and revert changes with minimal impact on the rest of the project.

Example

When you're starting a new project, git add serves the same function as svn import . To create an initial commit of the current directory, use the following two commands:

git add . git commit

Once you've got your project up-and-running, new files can be added by passing the path to git add :

git add hello.py git commit

The above commands can also be used to record changes to existing files. Again, Git doesn't differentiate between staging changes in new files vs. changes in files that have already been added to the repository.

git commit

The git commit command commits the staged snapshot to the project history. Committed snapshots can be thought of as "safe" versions of a project-Git will never change them unless you explicity ask it to. Along with git add , this is one of the most important Git commands.

While they share the same name, this command is nothing like svn commit . Snapshots are committed to the local repository, and this requires absolutely no interaction with other Git repositories.

Usage

git commit

Commit the staged snapshot. This will launch a text editor prompting you for a commit message. After you've entered a message, save the file and close the editor to create the actual commit. git commit -m "<message>"

Commit the staged snapshot, but instead of launching a text editor, use <message> as the commit message.

git commit -a

Commit a snapshot of all changes in the working directory. This only includes modifications to tracked files (those that have been added with git add at some point in their history).

Discussion

Snapshots are always committed to the local repository. This is fundamentally different from SVN, wherein the working copy is committed to the central repository. In contrast, Git doesn't force you to interact with the central repository until you're ready. Just as the staging area is a buffer between the working directory and the project history, each developer's local repository is a buffer between their contributions and the central repository.

This changes the basic development model for Git users. Instead of making a change and committing it directly to the central repo, Git developers have the opportunity to accumulate commits in their local repo. This has many advantages over SVN-style collaboration: it makes it easier to split up a feature into atomic commits, keep related commits grouped together, and clean up local history before publishing it to the central repository. It also lets developers work in an isolated environment, deferring integration until they're at a convenient break point.

Snapshots, Not Differences

Aside from the practical distinctions between SVN and Git, their underlying implementation also follow entirely divergent design philosophies. Whereas SVN tracks differences of a file, Git's version control model is based on snapshots . For example, an SVN commit consists of a diff compared to the original file added to the repository. Git, on the other hand, records the entire contents of each file in every commit.

This makes many Git operations much faster than SVN, since a particular version of a file doesn't have to be "assembled" from its diffs-the complete revision of each file is immediately available from Git's internal database.

Git's snapshot model has a far-reaching impact on virtually every aspect of its version control model, affecting everything from its branching and merging tools to its collaboration workflows.

Example

The following example assumes you've edited some content in a file called hello.py and are ready to commit it to the project history. First, you need to stage the file with git add , then you can commit the staged snapshot.

git add hello.py git commit

This will open a text editor (customizable via git config ) asking for a commit message, along with a list of what's being committed:

# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # #modified: hello.py

Git doesn't require commit messages to follow any specific formatting constraints, but the canonical format is to summarize the entire commit on the first line in less than 50 characters, leave a blank line, then a detailed explanation of what's been changed. For example:

Change the message displayed by hello.py - Update the sayHello() function to output the user's name - Change the sayGoodbye() function to a friendlier message

Note that many developers also like to use present tense in their commit messages. This makes them read more like actions on the repository, which makes many of the history-rewriting operations more intuitive.

How do I pull from a Git repository through an HTTP proxy

Stack Overflow
Note: while the use-case described is about using submodules within a project, the same applies to a normal git clone of a repository over HTTP.

I have a project under Git control. I'd like to add a submodule:

git submodule add http://github.com/jscruggs/metric_fu.git vendor/plugins/metric_fu

But I get

...
got 1b0313f016d98e556396c91d08127c59722762d0
got 4c42d44a9221209293e5f3eb7e662a1571b09421
got b0d6414e3ca5c2fb4b95b7712c7edbf7d2becac7
error: Unable to find abc07fcf79aebed56497e3894c6c3c06046f913a under http://github.com/jscruggs/metri...
Cannot obtain needed commit abc07fcf79aebed56497e3894c6c3c06046f913a
while processing commit ee576543b3a0820cc966cc10cc41e6ffb3415658.
fatal: Fetch failed.
Clone of 'http://github.com/jscruggs/metric_fu.git' into submodule path 'vendor/plugins/metric_fu'

I have my HTTP_PROXY set up:

c:\project> echo %HTTP_PROXY%
http://proxy.mycompany:80

I even have a global Git setting for the http proxy:

c:\project> git config --get http.proxy
http://proxy.mycompany:80

Has anybody gotten HTTP fetches to consistently work through a proxy? What's really strange is that a few project on GitHub work fine (awesome_nested_set for example), but others consistently fail (rails for example).

A:

You can also set the HTTP proxy that Git uses in global configuration property http.proxy:
C:\> git config --global http.proxy %HTTP_PROXY%

What finally worked was setting the $http_proxy environment variable. I had set $HTTP_PROXY correctly, but git apparently likes the lower-case version better.

There's some great answers on this already. However, I thought I would chip in as some proxy servers require you to authenticate with a user Id and password. Sometimes this can be on a domain.

So, for example if your proxy server configuration is as follows:

Server: myproxyserver
Port: 8080
Username: mydomain\myusername
Password: mypassword

Then, add to your .gitconfig file using the following command:

git config --global http.proxy http://mydomain\\myusername:mypassword@myproxyserver:8080

Don't worry about https. As long as the specified proxy server supports http, and https, then one entry in the config file will suffice.

You can then verify that the command added the entry to your .gitconfig file successfully by doing cat .gitconfig:

At the end of the file you will see an entry as follows:

[http]
    proxy = http://mydomain\\myusername:mypassword@myproxyserver:8080

Recommended Links

Softpanorama hot topic of the month

Softpanorama Recommended

Git (software) - Wikipedia, the free encyclopedia

Free Books

Git - Book

Basics

Youtube videos

Version Control with Git by Michael Koby

For more videos please go to http://www.codecasts.tv.

Git Branching and Merging Strategies - YouTube

GitHub Tutorials Lynda.com



Etc

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least


Copyright © 1996-2016 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case softpanorama.org is down you can use the at softpanorama.info

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Last modified: February 21, 2017