{"id":58367,"date":"2016-07-25T10:00:28","date_gmt":"2016-07-25T07:00:28","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=58367"},"modified":"2023-12-08T12:27:46","modified_gmt":"2023-12-08T10:27:46","slug":"git-tutorial","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html","title":{"rendered":"Git Tutorial &#8211; The Ultimate Guide (PDF Download)"},"content":{"rendered":"<p>Git is, without any doubt, the most popular version control system. Ironically, there are other version control systems easier to learn and to use, but, despite that, Git is the favorite option for developers, which is quite clarifying about the powerfulness of Git.<\/p>\n<p>This guide will cover all the topics needed to know in order to use Git properly, from explaining what is it and how it differs from other tools, to its usage, covering also advanced topics and practices that can suppose an added value to the process of version controlling.<\/p>\n<div class=\"toc\">\n<h3>Table of contents<\/h3>\n<dl>\n<dt><a href=\"#section_1\">1. What is version control? What is Git?<\/a><\/dt>\n<dt><a href=\"#section_2\">2. Git vs SVN (DVCS vs CVCS)<\/a><\/dt>\n<dt><a href=\"#section_3\">3. Download and install Git<\/a><\/dt>\n<dd><a href=\"#section_3_1\">3.1. Linux<\/a><\/dd>\n<dd><a href=\"#section_3_2\">3.2. Windows<\/a><\/dd>\n<dt><a href=\"#section_4\">4. Git usage<\/a><\/dt>\n<dd><a href=\"#section_4_1\">4.1. Creating a repository<\/a><\/dd>\n<dd><a href=\"#section_4_2\">4.2. Creating the history: commits<\/a><\/dd>\n<dd><a href=\"#section_4_3\">4.3. Viewing the history<\/a><\/dd>\n<dd><a href=\"#section_4_4\">4.4. Independent development lines: branches<\/a><\/dd>\n<dd><a href=\"#section_4_5\">4.5. Combining histories: merging branches<\/a><\/dd>\n<dd><a href=\"#section_4_6\">4.6. Conflictive merges<\/a><\/dd>\n<dd><a href=\"#section_4_7\">4.7. Checking differences<\/a><\/dd>\n<dd><a href=\"#section_4_8\">4.8. Tagging important points<\/a><\/dd>\n<dd><a href=\"#section_4_9\">4.9. Undoing and deleting things<\/a><\/dd>\n<dt><a href=\"#section_5\">5. Branching strategies<\/a><\/dt>\n<dd><a href=\"#section_5_1\">5.1. Long running branches<\/a><\/dd>\n<dd><a href=\"#section_5_2\">5.2. One version, one branch<\/a><\/dd>\n<dd><a href=\"#section_5_3\">5.3. Regardless the branching strategy: one branch for each bug<\/a><\/dd>\n<dt><a href=\"#section_6\">6. Remote repositories<\/a><\/dt>\n<dd><a href=\"#section_6_1\">6.1. Writing changes in the remote<\/a><\/dd>\n<dd><a href=\"#section_6_2\">6.2. Cloning a repository<\/a><\/dd>\n<dd><a href=\"#section_6_3\">6.3. Updating remote references: fetching<\/a><\/dd>\n<dd><a href=\"#section_6_4\">6.4. Fetching and merging remotes at once: pulling<\/a><\/dd>\n<dd><a href=\"#section_6_5\">6.5. Conflicts updating remote repository<\/a><\/dd>\n<dd><a href=\"#section_6_6\">6.6. Deleting things in remote repository<\/a><\/dd>\n<dt><a href=\"#section_7\">7. Patches<\/a><\/dt>\n<dd><a href=\"#section_7_1\">7.1. Creating patches<\/a><\/dd>\n<dd><a href=\"#section_7_2\">7.2. Applying patches<\/a><\/dd>\n<dt><a href=\"#section_8\">8. Cherry picking<\/a><\/dt>\n<dt><a href=\"#section_9\">9. Hooks<\/a><\/dt>\n<dd><a href=\"#section_9_1\">9.1. Client-side hooks<\/a><\/dd>\n<dd><a href=\"#section_9_2\">9.2. Server-side hooks<\/a><\/dd>\n<dd><a href=\"#section_9_3\">9.3. Hooks are not included in the history<\/a><\/dd>\n<dt><a href=\"#section_10\">10. An approach to Continuous Integration<\/a><\/dt>\n<dt><a href=\"#section_11\">11. Conclusion<\/a><\/dt>\n<dt><a href=\"#section_12\">12. Resources<\/a><\/dt>\n<\/dl>\n<\/div>\n<h2 id=\"section_1\">1. What is version control? What is Git?<\/h2>\n<p>Version control is the management of the changes made within a system, that it has not to be software necessarily.<\/p>\n<p>Even if you have never used before Git or similar tools, you will probably have ever carried out a version control. A very used and <em>bad<\/em> practice in software developing is, when the software has reached a stable situation, saving a local copy of it, identifying it as stable, and then following with the changes in other copy.<\/p>\n<p>This is something that <strong>every<\/strong> software engineer has done before using specific tools version controlling, so don&#8217;t feel bad if you have done it. Actually, this is much more better than having commented the code like:<\/p>\n<pre class=\"brush:java\">\/* First version\npublic void foo(int bar) {\n    return bar + 1;\n}\n*\/\n\/* Second version\npublic void foo(int bar) {\n    return bar - 1;\n}\n*\/\npublic void foo(int bar) {\n    return bar * 2;\n}<\/pre>\n<p>Which should be declared illegal.<\/p>\n<p>The <strong>version control systems (VCS)<\/strong> are designed for carrying out a proper management of the changes. These tools provide the following features:<\/p>\n<ul>\n<li>Reversibility.<\/li>\n<li>Concurrency.<\/li>\n<li>Annotation.<\/li>\n<\/ul>\n<p>The reversibility is the main capability of a VCS, allowing to return to any point of the history of the source code, for example, when a bug has been introduced and the code has to return to a stable point.<\/p>\n<p>The concurrency allows to have several people making changes on the same project, facilitating the process of the integration of pieces of code developed by two or more developers.<\/p>\n<p>The annotation is the feature that allows to add additional explanations and thoughts about the changes made, such us a resume of the changes made, the reason that has caused these changes, an overall description of the stability, etc.<\/p>\n<p>With this, <strong>the VCSs solve one of the most common problems of software development: the fear for changing the software<\/strong>. You will be probably be familiar to the famous saying &#8220;if something works, don&#8217;t change it&#8221;. Which is almost a joke, but, actually, is like we act many times. <strong>A VCS will help you to get rid of being scared about changing your code<\/strong>.<\/p>\n<p>There are several models for the version control systems. The one we mentioned, the manual process, can be considered as a local version control system, since the changes are only saved locally.<\/p>\n<p>Git is a <strong>distributed<\/strong> version control system (DVCS), also known as decentralized. This means that <strong>every developer has a full copy of the repository<\/strong>, which is hosted in the cloud.<\/p>\n<p>We will see more in detail the features of DVCSs in the following chapter.<\/p>\n<h2 id=\"section_2\">2. Git vs SVN (DVCS vs CVCS)<\/h2>\n<p>Before the DVCSs burst into the version controlling world, the most popular VCS was, probably Apache Subversion (known also as SVN). This VCS was centralized (CVCS). A centralized VCS is a system designed to have <strong>a single full copy of the repository, hosted in some server, where the developers save the changes they made<\/strong>.<\/p>\n<p>Of course, using a CVCS is better than having a local version control, which is incompatible with teamwork. But having a version control system that completely depends on a centralized server has an obvious implication: if the server, or the connection to it goes down, the developers won&#8217;t be able to save the changes. Or even worse, if the central repository gets corrupted, and no backup exists, the history of the repository will be lost.<\/p>\n<p><strong>CVCSs can also be slow<\/strong>. Recording a change in the repository means making effective the change in the remote repository, so, it relies on the connection speed to the server.<\/p>\n<p>Returning to Git and DVCSs, with it, every developer has the full repository locally. So, the <strong>developers can save the changes whenever they want<\/strong>. If at certain moment the server hosting the repository is down, the developers can continue working without any problem. And the changes could be recorded into the shared repository later.<\/p>\n<p>Another difference with CVCSs, is that DVCSs, specially Git, are <strong>much more faster<\/strong>, since the changes are made locally, and the disk access is faster than network access, at least in normal situation.<\/p>\n<p>The differences between both systems could be summed up to the following: with a <strong>CVCS you are enforced to have a complete dependency on a remote server<\/strong> to carry out your version control, whereas <strong>with a DVCS the remote server is just an option<\/strong> to share the changes.<\/p>\n<div class=\"tip\"><strong>Tip<\/strong><br \/>\nYou may skip installation and jump directly to the <a href=\"#section_4\"><strong>beginning of the guide<\/strong><\/a> below.<\/div>\n<h2 id=\"section_3\">3. Download and install Git<\/h2>\n<h3 id=\"section_3_1\">3.1. Linux<\/h3>\n<p>As you probably have guessed, Git can be installed in Linux executing the following commands:<\/p>\n<pre class=\"brush:bash\">sudo apt-get update\nsudo apt-get install git<\/pre>\n<h3 id=\"section_3_2\">3.2. Windows<\/h3>\n<p>Firstly, we have to download the last stable release from <a href=\"https:\/\/git-scm.com\/downloads\">official page<\/a>.<\/p>\n<p>Run the executable, and click &#8220;next&#8221; button until you get to the following step:<\/p>\n<p><figure style=\"width: 499px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/Windows-install-1.jpg\" width=\"499\" height=\"387\" \/><figcaption class=\"wp-caption-text\">1. Configuring Git in Windows to use it through Git Bash only.<\/figcaption><\/figure><\/p>\n<p>Check the first option. The following options can be left as they come by default. You are about four or five &#8220;next&#8221; ago of having Git installed.<\/p>\n<p>Now, if you open the context menu (right click), you will see two new options:<\/p>\n<ul>\n<li>&#8220;Git GUI here&#8221;.<\/li>\n<li>&#8220;Git Bash here&#8221;.<\/li>\n<\/ul>\n<p>In this guide we will be using the bash. All the commands shown will be for their execution in this bash.<\/p>\n<h2 id=\"section_4\">4. Git usage<\/h2>\n<p>In this chapter, we will see how to use Git to start with our version controlling.<\/p>\n<h3 id=\"section_4_1\">4.1. Creating a repository<\/h3>\n<p>To begin using Git, we have first to create a repository, also known as &#8220;repo&#8221;. For that, in the directory where we want to have the repository, we have to execute:<\/p>\n<pre class=\"brush:bash\">git init<\/pre>\n<p>We have a Git repository! Note that a folder named <code>.git<\/code> has been created. The repository will be the directory where the <code>.git<\/code> folder is placed. This folder is the repository metadata, an embedded database. It&#8217;s better not to touch anything inside it while you are not familiarized with Git.<\/p>\n<h3 id=\"section_4_2\">4.2. Creating the history: commits<\/h3>\n<p>Git constructs the history of the repository with commits. <strong>A commit is a full snapshot of the repository, that is saved in the database<\/strong>. Every state of the files that are committed, will be recoverable later at any moment.<\/p>\n<p>When doing a commit, we have to choose which files are going to be committed; not all the repository has to be committed necessarily. This process is called <strong>staging<\/strong>, where files are <strong>added to the index<\/strong>. The Git index is <strong>where the data that is going to be saved in the commit is stored temporarily<\/strong>, until the commit is done.<\/p>\n<p>Let&#8217;s see how it works.<\/p>\n<p>We are going to create a file and add some content to it, for example:<\/p>\n<pre class=\"brush:bash\">echo 'My first commit!' &gt; README.txt<\/pre>\n<p>Adding this file, the status of the repository has changed, since a new file has been created in the <strong>working directory<\/strong>. We can check for the status of the repository with the <code>status<\/code> option:<\/p>\n<pre class=\"brush:bash\">git status<\/pre>\n<p>Which, in this case, would generate the following output:<\/p>\n<pre class=\"brush:bash\">On branch master\n\nInitial commit\n\nUntracked files:\n\u00a0 (use \"git add &lt;file&gt;...\" to include in what will be committed)\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 README.txt\n\nnothing added to commit but untracked files present (use \"git add\" to track)<\/pre>\n<p>What Git is saying is &#8220;<em>you have a new file in the repository directory, but this file is not yet selected to be committed<\/em>&#8220;.<\/p>\n<p>If we want to include this file the commit, remember that it has to be added to the index. This is made with the <code>add<\/code> command, as Git suggests in the output of <code>status<\/code> :<\/p>\n<pre class=\"brush:bash\">git add README.txt<\/pre>\n<p>Again, the status of the repository has changes:<\/p>\n<pre class=\"brush:bash\">On branch master\n\nInitial commit\n\nChanges to be committed:\n\u00a0 (use \"git rm --cached &lt;file&gt;...\" to unstage)\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 new file:\u00a0\u00a0 README.txt<\/pre>\n<p>Now, we can do the commit!<\/p>\n<pre class=\"brush:bash\">git commit<\/pre>\n<p>Now, the default text editor will be shown, where we have to type the commit message, and then save. <strong>If we leave the message empty, the commit will be aborted<\/strong>.<\/p>\n<p>Additionally, we can use the shorthand version with <code>-m<\/code> flag, specifying the commit message inline:<\/p>\n<pre class=\"brush:bash\">git commit -m 'Commit message for first commit!'<\/pre>\n<p>We can add all the files of the current directory, recursively, to the index, with <code>.<\/code>:<\/p>\n<pre class=\"brush:bash\">git add .<\/pre>\n<p>Note that the following:<\/p>\n<pre class=\"brush:bash\">echo 'Second commit!' &gt; README.txt\ngit add README.txt\necho 'Or is it the third?' &gt; README.txt\ngit commit -m 'Another commit'<\/pre>\n<p><strong>Would commit the file with <code>'Second commit!'<\/code> content, because it was the one added to the index, and then we changed the file of the working directory<\/strong>, not the one added to staging area. To commit the latest change, we would have to add again the file to the index, being the first added file overwritten.<\/p>\n<p>Git identifies each commit uniquely using SHA1 hash function, based on the contents of the committed files. So, each commit is identified with a 40 character-long hexadecimal string, like the following, for example: <code>de5aeb426b3773ee3f1f25a85f471750d127edfe<\/code>. Take into account that the commit message, commit date, or any other variable rather than the committed files&#8217; content (and size), are not included in the hash calculation.<\/p>\n<p>So, for our first two commit, the history would be the following:<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/1-Git-history.jpg\" alt=\"git two commits\" width=\"860\" height=\"260\" \/><figcaption class=\"wp-caption-text\">2. History of the repository, with two commits.<\/figcaption><\/figure><\/p>\n<p>Git shortens the checksum of each commit to 7 characters (whenever it&#8217;s possible), to make them more legible.<\/p>\n<p>Each commit points to the commit it has been created from, being this called the &#8220;ancestor&#8221;.<\/p>\n<p>Note that <code>HEAD<\/code> element. This is one of the most important element in Git. The <code>HEAD<\/code> is the element that points to the current point in the repository history. <strong>The contents of the working directory will be those that belong to the snapshot the <code>HEAD<\/code> is pointing to<\/strong>.<\/p>\n<p>We will see this <code>HEAD<\/code> more in detail later.<\/p>\n<h4>4.2.1. Tips for creating good commit messages<\/h4>\n<p>The commit message content is more important that it may seem at first sight. Git allows to add any kind of explanation for any change we made, without touching the source code, and we should always take advantage of this.<\/p>\n<p>For the message formatting, there&#8217;s an unwritten rule known as the <strong>50\/72 rule<\/strong>, which is so simple:<\/p>\n<ul>\n<li>One first line with a summary of no more than 50 characters.<\/li>\n<li>Wrap the subsequent explanations in lines of no more than 72 characters.<\/li>\n<\/ul>\n<p>This is based on how Git formats the output when we are reviewing the history.<\/p>\n<p>But, more important than this, is the content of the message itself. The first thing that comes to mind to write are the changes that have been made, which is not bad at all. But the commit object itself is a description of the changes that have been made in the source code. To make the commit messages useful, <strong>you should always include the reason that motivated the changes<\/strong>.<\/p>\n<h3 id=\"section_4_3\">4.3. Viewing the history<\/h3>\n<p>Of course, Git is able to show the history of the repository. For that, the <code>log<\/code> command is used:<\/p>\n<pre class=\"brush:bash\">git log<\/pre>\n<p>If you try it, you will see that the output is not very nice. The <code>log<\/code> command has many flags available to draw pretty graphs. Here&#8217;s a suggestion for using this command through this guide, even if graphs are shown for each scenario:<\/p>\n<pre class=\"brush:bash\">git log --all --graph --decorate --oneline<\/pre>\n<p>If you want, you can omit the <code>--oneline<\/code> flag for showing the full information of each commit.<\/p>\n<h3 id=\"section_4_4\">4.4. Independent development lines: branches<\/h3>\n<p>Branching is probably the most powerful feature of Git. <strong>A branch represents an independent development path<\/strong>. The branches coexist in the same repository, but each one has its own history. In the previous section, we have worked with a branch, Git&#8217;s default branch, which is named <code>master<\/code>.<\/p>\n<p>Taking into account this, the proper way to express the history would be the following, considering\u00a0the branches.<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/2-History-with-master.jpg\" alt=\"git branch pointer\" width=\"860\" height=\"475\" \/><figcaption class=\"wp-caption-text\">3. History of the repository, showing the branch pointer.<\/figcaption><\/figure><\/p>\n<p>Creating a branch with Git is so simple:<\/p>\n<pre class=\"brush:bash\">git branch &lt;branch-name&gt;<\/pre>\n<p>For example:<\/p>\n<pre class=\"brush:bash\">git branch second-branch<\/pre>\n<p>And that&#8217;s it.<\/p>\n<p>But, what is Git doing really when it creates a branch? It just creates a pointer with that branch name that points to the commit where the branch has been created:<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/3-Two-branches.jpg\" width=\"860\" height=\"633\" \/><figcaption class=\"wp-caption-text\">4. History of the repository with a new branch.<\/figcaption><\/figure><\/p>\n<p>This is one of the most notable features of Git: the branch creation speed, almost instantaneous, regardless of the repository size.<\/p>\n<p>To start working in that branch, we have to <code>checkout<\/code> it:<\/p>\n<pre class=\"brush:bash\">git checkout second-branch<\/pre>\n<p>Now, the commits will only exist in <code>second-branch<\/code>. Why? <strong>Because the <code>HEAD<\/code> now is pointing to <code>second-branch<\/code>, so, the history created from now will have an independent path from <code>master<\/code><\/strong>.<\/p>\n<p>We can see it making a couple of commits being located in <code>second-branch<\/code>:<\/p>\n<pre class=\"brush:bash\">echo 'The changes made in this branch...' &gt;&gt; README.txt \ngit add README.txt \ngit commit -m 'Start changes in second-branch'\necho '... Only exist in this branch' &gt;&gt; README.txt \ngit add README.txt \ngit commit -m 'End changes in second-branch'<\/pre>\n<p>If we check for the content of the file we have being modifying, we will see the following:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:bash\">Second commit!\nThe changes made in this branch...\n... Only exist in this branch<\/pre>\n<p>But, what if we return to <code>master<\/code>?<\/p>\n<pre class=\"brush:bash\">git checkout master<\/pre>\n<p>The content of the file will be:<\/p>\n<pre class=\"brush:bash\">Second commit!<\/pre>\n<p>This is because, after creating the history of <code>second-branch<\/code>, we have placed the <code>HEAD<\/code> pointing to <code>master<\/code>:<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption alignnone\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/Two-histories.jpg\" alt=\"git 2nd branch\" width=\"860\" height=\"606\" \/><figcaption class=\"wp-caption-text\">5. Independent history for second-branch.<\/figcaption><\/figure><\/p>\n<h3 id=\"section_4_5\">4.5. Combining histories: merging branches<\/h3>\n<p>In the previous subsection, we have seen how we can create different paths for our repository history. Now, we are going to see how to combine them, what for Git is calling <strong>merging<\/strong>.<\/p>\n<p>Let&#8217;s suppose that, after the changes made in <code>second-branch<\/code>, is ready to return to <code>master<\/code>. For that, we have to place the <code>HEAD<\/code> in the destination branch (<code>master<\/code>), and specify the branch that is going to be merged to this destination branch (<code>second-branch<\/code>), with <code>merge<\/code> command:<\/p>\n<pre class=\"brush:bash\">git checkout master\ngit merge second-branch<\/pre>\n<p>And Git will give the following output:<\/p>\n<pre class=\"brush:bash\">Updating f043d98..0705117\nFast-forward\n\u00a0README.txt | 2 ++\n\u00a01 file changed, 2 insertions(+)<\/pre>\n<p>Now, the history of the\u00a0<code>second-branch<\/code> has been merged to <code>master<\/code>, so, all the changes made in this first branch have been applied to the second.<\/p>\n<p>In this case, the entire history of second-branch is now part of the history of master, having a graph like the following:<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/4-Fast-forward.jpg\" alt=\"git merge to master\" width=\"860\" height=\"489\" \/><figcaption class=\"wp-caption-text\">6. History after merging second-branch to master.<\/figcaption><\/figure><\/p>\n<p>As you can see, no track of the life of <code>second-branch<\/code> has been saved, when you probably were expecting a nice tree.<\/p>\n<p>This is because Git merged the branch using the <code>fast-forward<\/code> mode. Note that is telling it in the merge output, shown above. Why did Git do this? <strong>Because <code>master<\/code> and <code>second-branch<\/code> shared the common ancestor<\/strong>, <code>f043d98<\/code>.<\/p>\n<p>When we are merging branches, <strong>is always advisable not to use the\u00a0<code>fast-forward<\/code> mode<\/strong>. This is achieved passing <code>--no-ff<\/code> flag while merging:<\/p>\n<pre class=\"brush:bash\">git merge --no-ff second-branch<\/pre>\n<p>What does this really do? Well, it just creates an intermediate, third commit, between the <code>HEAD<\/code>, and the &#8220;from&#8221; branch&#8217;s last commit.<\/p>\n<p>After saving the commit message (of course, is editable), the branch will be merged, having the following history:<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/No-ff-merge.jpg\" alt=\"git no fast forward mode\" width=\"860\" height=\"485\" \/><figcaption class=\"wp-caption-text\">7. History after merging second-branch to master, using no fast-forward mode.<\/figcaption><\/figure><\/p>\n<p>Which is much more expressive, since the history is reflected as it is actually is. <strong>The no fast-forward mode should be always used<\/strong>.<\/p>\n<p>A merge of a branch supposes the end of the life of this. So, it should be deleted:<\/p>\n<pre class=\"brush:bash\">git branch -d second-branch<\/pre>\n<p>Of course, in the future, you can create again a <code>second-branch<\/code> named branch.<\/p>\n<h3 id=\"section_4_6\">4.6. Conflictive merges<\/h3>\n<p>In the previous section we have seen an &#8220;automatic&#8221; merge, i.e., Git has been able to merge both histories. Why? Because of the previously mentioned <strong>common ancestor<\/strong>. That is, the branch is returning to the point it started from.<\/p>\n<p>But, when the branch another branch borns from suffers changes, problems appear.<\/p>\n<p>To understand this, let&#8217;s construct a new history, which will have the following graph:<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption alignnone\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/Conflictive-histories.jpg\" alt=\"git after 2nd branch\" width=\"860\" height=\"808\" \/><figcaption class=\"wp-caption-text\">8. Continuing the history of master, after the creation of second-branch.<\/figcaption><\/figure><\/p>\n<p>With the following commands:<\/p>\n<pre class=\"brush:bash\">echo 'one' &gt;&gt; file.txt\ngit add file.txt\ngit commit -m 'first'\n\necho 'two' &gt;&gt; file.txt\ngit add file.txt \ngit commit -m 'second'\n\ngit checkout -b second-branch\n\necho 'three (from second-branch)' &gt;&gt; file.txt \ngit add file.txt \ngit commit -m 'third from second branch'\n\ngit checkout master\n\necho 'three' &gt;&gt; file.txt \ngit add file.txt \ngit commit -m 'third'<\/pre>\n<p>What will happen if we try to merge <code>second-branch<\/code> to <code>master<\/code>?<\/p>\n<pre class=\"brush:bash\">git checkout master\ngit merge second-branch<\/pre>\n<p>Git won&#8217;t be able to do it:<\/p>\n<pre class=\"brush:bash\">CONFLICT (content): Merge conflict in file.txt\nAutomatic merge failed; fix conflicts and then commit the result.<\/pre>\n<p><strong> Git doesn&#8217;t know how to do it, because the changes made in <code>second-branch<\/code> are not directly applicable to <code>master<\/code>, since it has changed from this first branch inception<\/strong>. What Git has done is to indicate in which parts exists these incompatibilities.<\/p>\n<p>Note that we haven&#8217;t used the <code>--no-ff<\/code> flag, since we now in advance that the fast-forward won&#8217;t be possible.<\/p>\n<p>If we check the <code>status<\/code>, we will see the following:<\/p>\n<pre class=\"brush:bash\">On branch master\nYou have unmerged paths.\n\u00a0 (fix conflicts and run \"git commit\")\n\nUnmerged paths:\n\u00a0 (use \"git add &lt;file&gt;...\" to mark resolution)\n\n\u00a0\u00a0 \u00a0both modified:\u00a0\u00a0\u00a0\u00a0\u00a0 file.txt<\/pre>\n<p>Showing the conflictive files. If we open it, we will see that Git has added some strange lines:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">one\ntwo\n&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD\nthree\n=======\nthree (from second-branch)\n&gt;&gt;&gt;&gt;&gt;&gt;&gt; second-branch<\/pre>\n<p>Git has indicated which are the incompatible changes. And how does it know? <strong>The incompatible changes are those that have been introduced into the &#8220;to&#8221; merging branch (<code>master<\/code>) since the creation of the &#8220;from&#8221; merging branch (<code>second-branch<\/code>)<\/strong>.<\/p>\n<p>Now, we have to decide how to combine the changes. On the one hand, the changes introduced to the current <code>HEAD<\/code> are shown (between <code>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD<\/code> and <code>=======<\/code>), and, on the other, the branch we are trying to merge (between <code>=======<\/code> and <code>&gt;&gt;&gt;&gt;&gt;&gt;&gt; second-branch<\/code>). To solve the conflict, there are three options:<\/p>\n<ul>\n<li>Use\u00a0<code>HEAD<\/code> version.<\/li>\n<li>Use <code>second-branch<\/code> version.<\/li>\n<li>A combination of two versions.<\/li>\n<\/ul>\n<p>Regardless the option, the file should end without any of the metacharacters that Git has added to identify the conflicts.<\/p>\n<p>Once the conflicts have been resolved, we have to add the file to the index and continue with the merge, with <code>commit<\/code> command:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">git add file.txt\ngit commit<\/pre>\n<p>Once saved the commit, the merge will be done, having Git created a third commit for this merge, as with when we used the <code>--no-ff<\/code> in the previous section.<\/p>\n<h4>4.6.1. Knowing in advance which version to stay with<\/h4>\n<p>It may happen that we know beforehand which version we want to choose in case of conflicts. In these cases, we can tell Git which version use, to make it apply it directly.<\/p>\n<p>To do this, we have to pass the <code>-X<\/code> option to <code>merge<\/code>, indicating which version use:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">git merge -X &lt;ours|theirs&gt; &lt;branch-name&gt;<\/pre>\n<p>So, for using <code>HEAD<\/code> version, we would have to use <code>ours<\/code> option; instead, for using the version that is not <code>HEAD<\/code>&#8216;s, <code>theirs<\/code> has to be passed.<\/p>\n<p>That is, the following:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">git merge -X ours second-branch<\/pre>\n<p>Would leave the file as is shown:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">one\ntwo\nthree<\/pre>\n<p>And, the following:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">git merge -X theirs second-branch<\/pre>\n<p>As it follows:<\/p>\n<pre class=\"brush:bash;highlight:[3,5,7]\">one\ntwo\nthree (from second-branch)<\/pre>\n<p>[ulp id=&#8217;qqpFiv5a5W384Wlg&#8217;]<br \/>\n&nbsp;<\/p>\n<h3 id=\"section_4_7\">4.7. Checking differences<\/h3>\n<p>Git allows to check the differences between distinct points in the history. This is done with <code>diff<\/code> option.<\/p>\n<h4>4.7.1. Interpreting the differences<\/h4>\n<p>Before seeing what differences we can look at, firstly we have to understand how the differences are shown.<\/p>\n<p>Let&#8217;s see a sample output of a difference between the same file:<\/p>\n<pre class=\"brush:bash\">diff --git a\/README.txt b\/README.txt\nindex 31325b6..55e8d58 100644\n--- a\/README.txt\n+++ b\/README.txt\n@@ -1,2 +1,2 @@\n-This is\n-the original file\n+This file\n+has been modified<\/pre>\n<p>Here, <code>a<\/code> is the a previous version of the file, and <code>b<\/code> the current version.<\/p>\n<p>The third and fourth line identifies each letter with a <code>-<\/code> or <code>+<\/code> symbol.<\/p>\n<p>That <code>@@ -1,2 +1,2 @@<\/code> is called &#8220;hunk header&#8221;. This identifies the chunks of code that actually have changed, not showing the common parts for both versions.<\/p>\n<p>The format is the following:<\/p>\n<pre class=\"brush:bash\">@@ &lt;previous&gt;&lt;from-line&gt;,&lt;number-of-lines&gt; &lt;current&gt;,&lt;from-line&gt;&lt;number-of-lines&gt;<\/pre>\n<p>In this case:<\/p>\n<ul>\n<li>&#8220;previous&#8221;: identified with <code>-<\/code>, corresponding to <code>a<\/code>.<\/li>\n<li>&#8220;from-line&#8221;: the line number from where the changes start.<\/li>\n<li>&#8220;number-of-lines&#8221;: the number of lines shown.<\/li>\n<li>&#8220;current&#8221;: identified with <code>+<\/code>, corresponding to <code>b<\/code>.<\/li>\n<\/ul>\n<p>Finally, which lines are subtracted, and which added, are shown. In this case, two lines have been subtracted from the line (those preceded with <code>-<\/code>), and other two have been added (preceded with <code>+<\/code>).<code><\/code><\/p>\n<h4>4.7.2. Differences between working directory and last commit<\/h4>\n<p>One common use is to check the differences between the working directory and the last commit. For this, is enough to execute:<\/p>\n<pre class=\"brush:bash\">git diff<\/pre>\n<p>Which will show the difference for every file. We can specify also specific files:<\/p>\n<pre class=\"brush:bash\">git diff &lt;file1&gt; &lt;file2&gt;<\/pre>\n<h4>4.7.3. Differences between exact points in history<\/h4>\n<p>We can look for differences with:<\/p>\n<ul>\n<li>SHA1 id<\/li>\n<li>Branch names<\/li>\n<li><code>HEAD<\/code><\/li>\n<li>Tags<\/li>\n<\/ul>\n<p>Being combinable between them.<\/p>\n<p>The syntax is the following:<\/p>\n<pre class=\"brush:bash\">git diff &lt;original&gt;..&lt;modified&gt;<\/pre>\n<p>For example, the following would show the changes that have been applied to <code>dev<\/code> branch, compared to a <code>v1.0<\/code> tag:<\/p>\n<pre class=\"brush:bash\">git diff v1.0..dev<\/pre>\n<h3 id=\"section_4_8\">4.8. Tagging important points<\/h3>\n<p>Tagging is one of the nicest features of Git, since allows to mark important points in the repository history, in a very easy way. Usually, tags are used to mark releases, not only for stable releases, but also for under-development or incomplete releases, such as:<\/p>\n<ul>\n<li>Alpha<\/li>\n<li>Beta<\/li>\n<li>Release candidate (rc)<\/li>\n<\/ul>\n<p>Creating a tag is so simple, we just have to situate the <code>HEAD<\/code> in the point we want to tag, and just specify the tag name with the <code>tag<\/code> option:<\/p>\n<pre class=\"brush:bash\">git tag -a &lt;tag-name&gt;<\/pre>\n<p>For example:<\/p>\n<pre class=\"brush:bash\">git tag -a v0.1-beta1<\/pre>\n<p>Then, we will be asked to type a message for the tag. <strong>Typically, the changes made from last tag are specified<\/strong>.<\/p>\n<p>As when committing, we can specify the tag message inline, with <code>-m<\/code> flag:<\/p>\n<pre class=\"brush:bash\">git tag -a v0.1 -m 'v0.1 stable release, changes from...'<\/pre>\n<p>Take into account that the <strong>tag names cannot be repeated <\/strong>in a repository.<\/p>\n<h3 id=\"section_4_9\">4.9. Undoing and deleting things<\/h3>\n<p>Git also allows to undo and modify some things in the history. In this section we will see what can be done, and how.<\/p>\n<h4>4.9.1. Modifying the last commit<\/h4>\n<p>Is quite common to want to modify the last commit, for example, when just a line of code has to be added; or even to modify the update message, without changing any file.<\/p>\n<p>For that, Git has the <code>--amend<\/code> flag for <code>commit<\/code> command:<\/p>\n<pre class=\"brush:bash\">git commit --amend<\/pre>\n<p>This is just the same as committing, but, instead of a new commit object, the last one of that branch will be overwritten.<\/p>\n<h4>4.9.2. Discarding uncommitted changes<\/h4>\n<p>This is for, after a commit, when we keep developing, we think that we have taken an incorrect path, and we want to reset the changes, returning to the last commit&#8217;s state.<\/p>\n<p>For this, the command used is <code>checkout<\/code>, as for moving between branches. But, when specifying a file, this gets reseted to the state of the last commit.<\/p>\n<p>For example:<\/p>\n<pre class=\"brush:bash\">echo 'one' &gt; test.txt\ngit add test.txt \ngit commit -m 'commit one'\necho 'two' &gt; test.txt \ngit checkout test.txt # The content of test.txt is now 'one'.<\/pre>\n<h4>4.9.3. Deleting commits<\/h4>\n<p>Usually, we want to delete commits when we don&#8217;t want to leave any record of an embarrassing commit, or just for removing useless changes.<\/p>\n<p>This is achieved moving the branch or <code>HEAD<\/code> pointers. Moving the pointers to previous commits makes the commits remaining ahead get &#8220;lost&#8221;, unlinked from the linked list. To move them, <code>reset<\/code> command is used.<\/p>\n<p>There are two ways of making a reset: not touching the working directory (soft reset, <code>--soft<\/code> flag), or resetting it too (hard reset, <code>--hard<\/code> flag). That is, <strong>if you make a soft reset, the commit(s) will be removed, but the modifications saved in that\/those commit(s) will remain; and a hard reset, won&#8217;t leave change made in the commit(s)<\/strong>. If no flag is specified, the reset will be done softly.<\/p>\n<p>Let&#8217;s start resetting things. The following command would remove the last commit, i.e., the commit where <code>HEAD<\/code> is pointing to:<\/p>\n<pre class=\"brush:bash\">git reset --hard HEAD~<\/pre>\n<p>The <code>~<\/code> character is for indicating an ancestor. Used once, indicates the immediate parent; twice, the grandparent; and so on. But, instead of typing <code>~<\/code> <em>n<\/em> times, we can specify the <em>n<\/em> ancestors that we want to remove:<\/p>\n<pre class=\"brush:bash\">git reset --hard HEAD~3<\/pre>\n<p>Which would remove the last 3 commits.<\/p>\n<p>You may have noticed that this may cause conflicts with those commits with more than one ancestor, i.e., the result of a not fast-forwarded merge. Well, it doesn&#8217;t cause any problem: the followed parent using <code>HEAD~<\/code> is always the first one. But there&#8217;s a way to decide which of the common parents follow: <code>^<\/code>, followed by the parent number. So, the following:<\/p>\n<pre class=\"brush:bash\">git reset --hard HEAD~2^2<\/pre>\n<p>Would remove the previous two commits, but taking the path of the second ancestor.<\/p>\n<p>Even if it is possible to specify which ancestor path follow, <strong>is recommended to always use the syntax for first ancestor<\/strong> (only <code>~<\/code>) <strong>since it&#8217;s easier, even if more commands would be required<\/strong> (since you would have to checkout the different branches to update <code>HEAD<\/code> position).<\/p>\n<h4>4.9.4. Deleting tags<\/h4>\n<p>Deleting tags is so simple:<\/p>\n<pre class=\"brush:bash\">git tag -d &lt;tag-name&gt;<\/pre>\n<h2 id=\"section_5\">5. Branching strategies<\/h2>\n<p>Reached this point, you may have already asked your self: &#8220;<em>Okay, branches are cool, but when should I create and merge them?<\/em>&#8221;<\/p>\n<p>When we want to carry out a version control, we need to know\u00a0which strategy we are going to follow. <strong>Using Git without having a clear branching policy is a complete nonsense<\/strong>.<\/p>\n<p>The branching workflow to follow <strong>depends, mainly, on how we want to maintain the code<\/strong>. In this section, we will see the two main branching strategies.<\/p>\n<h3 id=\"section_5_1\">5.1. Long running branches<\/h3>\n<p>This strategy is used when we want <strong>to maintain a single version of our software at the same time<\/strong>. That is, when we offer the last version of our software as available, instead of having many versions (which can be still available, but considered as old or unmaintained).<\/p>\n<p>The key of this strategy is having a branch only for stable versions, where the releases are tagged, for which the default branch is used, <code>master<\/code>; and having other branches for development, where the features are developed, tested, and integrated.<\/p>\n<p>In this strategy, the <code>master<\/code> branch is the production branch, so <strong>only tested, properly integrated, definitive versions should be here. Or, there can also be under-development or not fully tested versions, but they must be properly tagged<\/strong>.<\/p>\n<p>The following graph shows an example of the history of a repository following this strategy:<\/p>\n<p><figure style=\"width: 786px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/Long-running-branches-1.jpg\" alt=\"git long running branches strategy\" width=\"786\" height=\"579\" \/><figcaption class=\"wp-caption-text\">9. Example of a repository history using the long-running branches strategy.<\/figcaption><\/figure><\/p>\n<p>Simple and clarifying. The production state is only modified for those changes that have been integrated with the development branch, where nothing happens if something breaks. The changes that have to be made for each feature are perfectly isolated, favoring the division of tasks among the teammates.<\/p>\n<h3 id=\"section_5_2\">5.2. One version, one branch<\/h3>\n<p>This workflow is thought <strong>for creating software that will be available and maintained for several versions<\/strong>. In other words, a release does not &#8220;overwrite&#8221; every previous releases, it would &#8220;overwrite&#8221; only the release of the branch the release has been made for.<\/p>\n<p>To achieve this, each maintained version has to have its main version, but with a common development path for all of them.<\/p>\n<p>This is done having a branch for every version (usually named <code>PROJECT_NAME_XX_STABLE<\/code> or similar) for the stable release, the &#8220;master&#8221; of each version; and having a main branch (and its sub-branches) where the development is made, for which default\u00a0<code>master<\/code> branch can be used. When each feature is developed and tested, the <code>master<\/code> branch can be merged to every wanted stable version.<\/p>\n<p>This branching strategy is based on the long-running, but, in this case, having many &#8220;masters&#8221; instead of a single one.<\/p>\n<p>Take into account that each feature should have to be tested with each version of the project we want to apply this feature to. Consider using Continuous Integration when dealing with this strategy.<\/p>\n<p>Let&#8217;s see an example of the graph of a history for which this strategy has been applied.<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/One-version-one-branch-1.jpg\" alt=\"git one branch strategy\" width=\"860\" height=\"701\" \/><figcaption class=\"wp-caption-text\">10. Example of a repository history using the one version, one branch strategy.<\/figcaption><\/figure><\/p>\n<p>As we can see, here, the\u00a0<code>master<\/code> branch is used as the main development branch.<\/p>\n<p>In the v3.0 version, we have simulated a bug for <code>feature1<\/code>. It does not have to be necessarily a bug appeared at integration time, it can be a bug that has been detected later. In any case, we are sure that bug of <code>feature1<\/code> only exists for v3.0 version. In these cases, we shouldn&#8217;t fix these bugs in\u00a0<code>master<\/code> branch, because it&#8217;s not something that affects all the versions. We should create a branch from the affected version, fix the bug, and merge to the specific branch. And, if the future the same error persists for new releases, we can consider the option of merging it to <code>master<\/code>.<\/p>\n<p>The main advantage of this strategy is that the common features follow a common path, and the specific changes can be perfectly isolated for the affected versions.<\/p>\n<h3 id=\"section_5_3\">5.3. Regardless the branching strategy: one branch for each bug<\/h3>\n<p>No matter the branching strategy you use, an advisable practice is to create an independent branch for every bug, as same as it has been reported in your bug tracker (because you use a bug tracking system, right?). Actually, we have seen this practice in the previous example, in the integration of the feature into the branch for v3.0 version. <strong>Having an independent branch for each bug allows to having the issues perfectly located and identified, having the changes fixed involves isolated from others<\/strong>.<\/p>\n<p>Identifying this branch with the id number generated by the bug tracker for the given bug, naming the branches, for example, as <code>issue-X<\/code>, allows to have a track between the changes made for the fix of that bug, to the comments made in the corresponding ticket of the bug tracker, which is really helpful, since you can explain possible solutions for the bugs, attach images, etc.<\/p>\n<h2 id=\"section_6\">6. Remote repositories<\/h2>\n<p>Git, as we have seen in the introduction, is a distributed VCS. This means that, apart from the local, we can have a copy of the repository hosted in a remote server that, apart from making public the source code of the project, is used for collaborative development.<\/p>\n<p>The most popular platform for Git repositories hosting is <a href=\"https:\/\/github.com\/\">GitHub<\/a>. Unfortunately, GitHub does not offer private repositories in its free plan. If you need a hosting platform with unlimited private repositories, you can use <a href=\"https:\/\/bitbucket.org\/\">Bitbucket<\/a>. And, if you are looking for hosting your repositories in your own server, the available option is <a href=\"https:\/\/about.gitlab.com\/\">GitLab<\/a>.<\/p>\n<p>For this section, we will need to use one of the options mentioned above.<\/p>\n<h3 id=\"section_6_1\">6.1. Writing changes in the remote<\/h3>\n<p>The first thing we need to do in the remote hosting is to create a repository, for which a URL with the following format will be created:<\/p>\n<pre class=\"brush:bash\">https:\/\/hosting-service.com\/username\/repository-name<\/pre>\n<p>Once having a remote repository, we have to link it with our local repo. This is made with the <code>remote add &lt;remote-name&gt; &lt;repo-url&gt;<\/code> command:<\/p>\n<pre class=\"brush:bash\">git remote add origin https:\/\/hosting-service.com\/username\/repository-name<\/pre>\n<p><code>origin<\/code> is which is named by default by Git, similarly to <code>master<\/code> branch, but it does not have to be necessarily.<\/p>\n<p>Now, in our local repository, the remote repository is identified as <code>origin<\/code>. We can now start to &#8220;send&#8221; information to it, which is made with <code>push<\/code> option:<\/p>\n<pre class=\"brush:bash\">git push [remote-name] [branch-name | --all] [--tags]<\/pre>\n<p>Let&#8217;s see some examples of how it works:<\/p>\n<pre class=\"brush:bash\">git push origin --all      # Updates the remote with all the local branches\ngit push origin master dev # Updates remote's mater and dev branches\ngit push origin --tags     # Sends tags to remotes<\/pre>\n<p>This is an example output of a successful master branch update:<\/p>\n<pre class=\"brush:bash\">Counting objects: 3, done.\nWriting objects: 100% (3\/3), 235 bytes | 0 bytes\/s, done.\nTotal 3 (delta 0), reused 0 (delta 0)\nTo https:\/\/hosting-service.com\/username\/repository-name.git\n\u00a0* [new branch]\u00a0\u00a0\u00a0\u00a0\u00a0 master -&gt; master<\/pre>\n<p>What has Git internally with this?<\/p>\n<p>Well, now, a directory <code>.git\/refs\/remotes<\/code> has been created, and, inside it, another directory, <code>origin<\/code> (because that&#8217;s the name we have given to the remote). Here, <strong>Git creates a file for each branch exiting in the remote repository, with a reference to it. This reference is just the SHA1 id of the last commit of the given branch of the remote repository<\/strong>. This is used by Git to know if in remote repo are any changes that can be applied to the local repository. We will cover this in detail later in the following sections.<\/p>\n<p><strong>Note<\/strong>: a repository can have as many remotes as we want. For example, we could have the remote of the same repository in both GitHub and Bitbucket:<\/p>\n<pre class=\"brush:bash\">git remote add github https:\/\/github.com\/username\/repository-name\ngit remote add bitbucket https:\/\/bitbucket.org\/username\/repository-name<\/pre>\n<h3 id=\"section_6_2\">6.2. Cloning a repository<\/h3>\n<p>The cloning of a repository is actually made once, when we are going to start to work with a remote repository.<\/p>\n<p>For cloning remote repositories there&#8217;s no mystery, we just have to use the <code>clone<\/code> option, specifying the URL of the repository:<\/p>\n<pre class=\"brush:bash\">git clone https:\/\/hosting-service.com\/username\/repository-name<\/pre>\n<p>Which would create a local directory with the repository, with the reference to the remote it has been cloned from.<\/p>\n<p>By default, when cloning a repository, only the default branch is created (<code>master<\/code>, generally). The way to create the other branches locally is making a checkout to them.<\/p>\n<p>Remote branches can be shown with <code>branch<\/code> option with <code>-r<\/code> flag:<\/p>\n<pre class=\"brush:bash\">git branch -r<\/pre>\n<p>They will be shown with the format <code>&lt;remote-name&gt;\/&lt;branch-name&gt;<\/code>. To create the local branch, is enough to make a checkout to <code>&lt;branch-name&gt;<\/code>.<\/p>\n<h3 id=\"section_6_3\">6.3. Updating remote references: fetching<\/h3>\n<p>Fetching the remote repository means <strong>updating the reference of a local branch, to put it even with the remote branch<\/strong>.<\/p>\n<p>Let&#8217;s consider a collaborative scenario where two developers are pushing changes to the same repo. In some moment, one of the developers wants to update its reference to <code>master<\/code>, to the last push of the other developer, as is shown in the following image.<\/p>\n<p><figure style=\"width: 860px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2016\/07\/Remote-1.jpg\" alt=\"git remote repository\" width=\"860\" height=\"673\" \/><figcaption class=\"wp-caption-text\">11. Collaborative development with a remote repository.<\/figcaption><\/figure><\/p>\n<p>The content of the <code>.git\/refs\/remotes\/origin\/master<\/code> file of Alice&#8217;s repository would be, before any update, the following:<\/p>\n<pre class=\"brush:bash\">5bfc81ce5f7a0b26b493be0c99f1966a1896c972<\/pre>\n<p>Bob&#8217;s, however, will be updated, since it has been him the last who has updated the remote repository:<\/p>\n<pre class=\"brush:bash\">37db4f82e346665f6048cc9e4b7cd48c83c6ebcb<\/pre>\n<p>Now, Alice wants to have in her local repository the changes made by Bob. For that, she has to <code>fetch<\/code> the <code>master<\/code> branch:<\/p>\n<pre class=\"brush:bash\">git fetch origin master<\/pre>\n<p>(Alternatively, she can fetch every branch with <code>--all<\/code> flag):<\/p>\n<pre class=\"brush:bash\">git fetch --all<\/pre>\n<p>The output of the fetch would be something similar to the following:<\/p>\n<pre class=\"brush:bash\">remote: Counting objects: 3, done.\nremote: Total 3 (delta 0), reused 0 (delta 0)\nUnpacking objects: 100% (3\/3), done.\nFrom https:\/\/hosting-service.com\/alice\/repository-name\n\u00a0* branch\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 master\u00a0\u00a0\u00a0\u00a0 -&gt; FETCH_HEAD\n\u00a0\u00a0 5bfc81c..37db4f8\u00a0 master\u00a0\u00a0\u00a0\u00a0 -&gt; origin\/master<\/pre>\n<p>And, now, the content of Alice&#8217;s <code>.git\/refs\/remotes\/origin\/master<\/code> file would be the same of remote&#8217;s:<\/p>\n<pre class=\"brush:bash\">37db4f82e346665f6048cc9e4b7cd48c83c6ebcb<\/pre>\n<p>With this, Alice has <strong>updated the reference to remote&#8217;s\u00a0<code>master<\/code> branch, but the changes have not been applied in the repository<\/strong>.<\/p>\n<p><code>fetch<\/code>\u00a0 does not apply changes directly to the local repository. Is the first of two steps that have to be made. The other step is to <strong>merge the remote branch, which has just been updated; with the local branch<\/strong>. This is just a merge as any other, but where the remote name has to be indicated:<\/p>\n<pre class=\"brush:bash\">git merge origin\/master<\/pre>\n<p>Once the merge is finished, Alice will have the latest version of <code>master<\/code> branch.<\/p>\n<p><strong>Note<\/strong>: in this merge, we have not applied the no-fast forward. In this cases, would not have many sense to apply it, since we are merging the intrinsically same branch, but that is located somewhere else.<\/p>\n<h3 id=\"section_6_4\">6.4. Fetching and merging remotes at once: pulling<\/h3>\n<p>Git has an option to apply remote changes at once, that is, fetching and merging the branch in one command. This option is <code>pull<\/code>.<\/p>\n<p>Considering the exactly same scenario seen above, we could just execute:<\/p>\n<pre class=\"brush:bash\">git pull origin master<\/pre>\n<p>And would do the fetch, followed by the merge.<\/p>\n<p>Use the way you fell more comfortable with. There&#8217;s no <em>better<\/em> way; actually, they do exactly the same, but expressed differently.<\/p>\n<h3 id=\"section_6_5\">6.5. Conflicts updating remote repository<\/h3>\n<p>Let&#8217;s return to the scenario shown above. What would happen if, without updating her local repository, Alice would create a commit and push it to the remote repository? Well, she would receive an ugly message from Git:<\/p>\n<pre class=\"brush:bash\">\u00a0! [rejected]\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 master -&gt; master (fetch first)\nerror: failed to push some refs to 'https:\/\/hosting-service.com\/alice\/repository-name.git'\nhint: Updates were rejected because the remote contains work that you do\nhint: not have locally. This is usually caused by another repository pushing\nhint: to the same ref. You may want to first integrate the remote changes\nhint: (e.g., 'git pull ...') before pushing again.\nhint: See the 'Note about fast-forwards' in 'git push --help' for details.<\/pre>\n<p>The push would be rejected because Alice <strong>has not continued the history of the repository from a point that has been already registered in the remote<\/strong>. So, before writing changes in the remote repository, she would need first to fetch &amp; merge, or pull, the remote with her changes.<\/p>\n<h4>6.5.1. A bad way to resolve conflicts<\/h4>\n<p>There&#8217;s still another way, which can not be exactly considered as <em>resolving<\/em>. Is about forcing pushes with <code>--force<\/code> flag.<\/p>\n<p>Forcing a push is about, basically, one thing: overwrite the remote repository branch (or the whole repository) with the one that is being pushed. So, in the above scenario, if Alice forces a push of her repository, the <code>37db4f8<\/code> commit will disappear. <strong>This would leave Bob working in something similar to a &#8220;parallel universe&#8221; that cannot coexist with the current reality of the project<\/strong>, since his work is based on a state that no longer exist in the project.<\/p>\n<p>In conclusion, <strong>don&#8217;t force pushes when you are working with other developers<\/strong>, at least if you don&#8217;t want to have an intense argument with them.<\/p>\n<p>If you Google for &#8220;git force push&#8221; in the images section, you will see some memes that perfectly explain graphically what a forced push is considered as.<\/p>\n<h3 id=\"section_6_6\">6.6. Deleting things in remote repository<\/h3>\n<p>As with forced pushes, things in remote repositories must be deleted with extreme precaution. <strong>Before deleting anything, every collaborator should be informed about it<\/strong>.<\/p>\n<p>Actually, when we are pushing commits, branches, etc., we are pushing them to a ref destination, but we don&#8217;t have to specify the destination explicitly.<\/p>\n<p>The explicit syntax is the following:<\/p>\n<pre class=\"brush:bash\">git push origin &lt;source&gt;:&lt;destination&gt;<\/pre>\n<p>So, the way of deleting remote things is updating the refs to prior states, or pushing &#8220;nothing&#8221;.<\/p>\n<p>Let&#8217;s see how to do it for every case.<\/p>\n<h4>6.6.1. Deleting commits<\/h4>\n<p>This is just the same as deleting commits locally, for example, to delete the last two commits:<\/p>\n<pre class=\"brush:bash\">git push origin HEAD~2:master --force<\/pre>\n<p>If we are using <code>HEAD<\/code> to refer the commits to remove, we must ensure that it&#8217;s located on the same branch as remote.<\/p>\n<p>Note that these pushes have to be forced too.<\/p>\n<h4>6.6.2. Deleting branches<\/h4>\n<p>This is quite simple, is just about pushing &#8220;nothing&#8221;, as said before. The following would remove <code>dev<\/code> branch from remote repository:<\/p>\n<pre class=\"brush:bash\">git push origin :dev<\/pre>\n<p><strong>Remote branches should be removed when the local branch is removed<\/strong>.<\/p>\n<h4>6.6.3. Deleting tags<\/h4>\n<p>As same as with branches, we have to push &#8220;nothing&#8221;, e.g.:<\/p>\n<pre class=\"brush:bash\">git push origin --tags :v1.0<\/pre>\n<h2 id=\"section_7\">7. Patches<\/h2>\n<p>You will have probably ever seen a software being updated with something called <em>patch<\/em>. A patch is just a file that describes the changes that have to be made over a program, indicating which code lines have to be removed, and which have to be added. With Git, a path is just the output of a\u00a0<code>diff<\/code> saved into a file.<\/p>\n<p>Take into account that a patch is an update, but an update does not have to be a patch necessarily. <strong>Patches are thought for hotfixes<\/strong>, or also critical features that have to be fixed or implemented <em>right now<\/em>, not for being the common update and deploying strategy.<\/p>\n<h3 id=\"section_7_1\">7.1. Creating patches<\/h3>\n<p>As said, a patch for Git is just the output of a <code>diff<\/code>. So, we would have to redirect that output to a file:<\/p>\n<pre class=\"brush:bash\">git diff &lt;expression&gt; &gt; &lt;patch-name&gt;.patch # The extension is not important.<\/pre>\n<p>For example:<\/p>\n<pre class=\"brush:bash\">git diff master..issue-1 &gt; issue-1-fix.patch<\/pre>\n<p><strong>Note<\/strong>: a patch cannot be modified. <strong>If a patch file suffers any modification, Git will mark it as corrupt and it won&#8217;t apply it.<\/strong><\/p>\n<h3 id=\"section_7_2\">7.2. Applying patches<\/h3>\n<p>The patches are applied with <code>apply<\/code> command. It&#8217;s as simple as specifying the path to the path file:<\/p>\n<pre class=\"brush:bash\">git apply &lt;patch-file&gt;<\/pre>\n<p>If patching goes well, no message will be displayed (if you haven&#8217;t used the <code>--verbose<\/code> flag). If the patch is not applicable, Git will show which are the files causing problems.<\/p>\n<p>Is quite common to get errors due to just whitespace differences. These errors can be ignored with <code>--ignore-space-change<\/code> and <code>--ignore-whitespace<\/code> flags.<\/p>\n<h2 id=\"section_8\">8. Cherry picking<\/h2>\n<p>There may be some scenarios in where we are interested in porting into a branch just a specific set of changes made on another branch, instead of merging it.<\/p>\n<p>To do this, Git allows to cherry pick commits from branches, with the <code>cherry-pick<\/code> command. The mechanism is the same as merging, but, in this case, specifying the commit SHA1 id, for example:<\/p>\n<pre class=\"brush:bash\">git cherry-pick -x aba6c1b # Several commits can be cherry picked.<\/pre>\n<p>A cherry pick creates a new commit, with the same message as the original&#8217;s one. The <code>-x<\/code> option is for adding to that commit message a line indicating that is a cherry pick, and from which commit has been picked:<\/p>\n<blockquote>\n<p>(cherry picked from commit aba6c1bf9a0a7d6d9ccceeab2b5dfc64f6c115c2)<\/p>\n<\/blockquote>\n<p><strong>The cherry picking should not be a recurrent practice in your workflow, since it does not leave a track in the history<\/strong>, just a line indicating where has been picked from.<\/p>\n<h2 id=\"section_9\">9. Hooks<\/h2>\n<p>Git hooks are <strong>custom scripts that are triggered when important events occur<\/strong>, for example, a commit or a merge.<\/p>\n<p>Let&#8217;s say that you want to notify someone with an email when your production branch is updated, or to run a test suite; but in an automated way. The hooks can do this for you.<\/p>\n<p>The scripts are located in <code>.git\/hooks<\/code> directory. By default, some sample hooks are provided. Each hook has to have a concrete name, that we will see later, with no extension; and has to be marked as executable. You can use other scripting languages such us PHP or Python, apart from shell code.<\/p>\n<p>There are two kind of hooks: client-side, and server-side.<\/p>\n<h3 id=\"section_9_1\">9.1. Client-side hooks<\/h3>\n<p>The client-side hooks are those that are fired when the local repository suffers changes. These are the most common:<\/p>\n<ul>\n<li><code>pre-commit<\/code>: invoked by <code>git commit<\/code> command, before the commit is saved. A commit can be aborted with this hook exiting with a non-zero status.<\/li>\n<li><code>post-commit<\/code>: invoked by <code>git commit<\/code> too, but this time when the commit has been saved. At this point, the commit cannot be aborted.<\/li>\n<li><code>post-merge<\/code>: as same as with <code>post-commit<\/code>, but being this one fired by <code>git merge<\/code>.<\/li>\n<li><code>pre-push<\/code>: fired by <code>git push<\/code>, before the remote any object has been transferred.<\/li>\n<\/ul>\n<p>The following script shows an example applicable for both\u00a0<code>post-commit<\/code> and\u00a0<code>post-commit<\/code> hooks, for notification purposes:<\/p>\n<pre class=\"brush:bash\">#!\/bin\/sh\n\nbranch=$(git rev-parse --abbrev-ref HEAD)\n\nif [ \"$branch\" = \"master\" ]; then\n\u00a0\u00a0\u00a0 echo \"Notifying release to everyone...\"\n\u00a0\u00a0\u00a0 # Send the notification...\nfi<\/pre>\n<p>To use it for both cases, you would have to create both hooks.<\/p>\n<h3 id=\"section_9_2\">9.2. Server-side hooks<\/h3>\n<p>These hooks reside in the server where the remote repository is hosted. As it is obvious, if you are using services such as GitHub for hosting your repositories, you won&#8217;t be permitted to execute arbitrary code. In GitHub&#8217;s case, you have available third-party services, but never hooks with your own code. For using executing your code, you will have to have your own server for hosting.<\/p>\n<p>The most used hooks are:<\/p>\n<ul>\n<li><code>pre-receive<\/code>: this is fired after someone makes a push, and before the references get updated in the remote. So, with this hook, you can deny any push.<\/li>\n<li><code>update<\/code>: almost exact to the previous one, but this is executed for each reference pushed. That is, if 5 references have been pushed, this hook will be executed 5 times, unlike <code>pre-receive<\/code>, which is executed for the push as a whole.<\/li>\n<li><code>post-receive<\/code>: this one is executed once the push has been successful, so it can be used for notification purposes also.<\/li>\n<\/ul>\n<h3 id=\"section_9_3\">9.3. Hooks are not included in the history<\/h3>\n<p>The hooks only exist in the local repository. If you make a push in a repository that has custom hooks, these will not be sent to the remote. So, if every developer should share the same hooks, they would have to be included in the working directory, and installed them manually.<\/p>\n<h2 id=\"section_10\">10. An approach to Continuous Integration<\/h2>\n<p>Continuous Integration (CI) is a software engineering practice that is closely related to version controlling, and it&#8217;s worth mentioning it, at least to know it conceptually.<\/p>\n<p><strong>CI consists on making several integrations of the code <\/strong>(at least, once a day)<strong>, in a completely automated way, with the aim of finding errors in early phases of the development<\/strong>.<\/p>\n<p>The concept is almost the same of the hooks, but in a much more <strong>scalable and maintainable way<\/strong>.<\/p>\n<p>Here are some of the actions that are performed in each integration:<\/p>\n<ul>\n<li>Test execution: unit, acceptance, integration, regression, and a large etc.<\/li>\n<li>Quality Assurance, with software metrics checking: cyclomatic complexity, code coverage, and another large etc.<\/li>\n<li>Software coding standard compliance checking.<\/li>\n<\/ul>\n<p>Continuous Integration allows to perform those actions, and more, automatically, without the need of having to execute it manually, <strong>just with a push or commit<\/strong>. Interesting, isn&#8217;t it?<\/p>\n<p>Probably, the most used CI options are the following:<\/p>\n<ul>\n<li>Travis CI: cloud-based, which allows to fire integrations with pushes, without the need of having your own server.<\/li>\n<li>Jenkins: self-hosted, for which a server is needed, but which is completely configurable. Compatible with many build tools, like Ant, Gradle, Maven, Phing, Grunt&#8230;<\/li>\n<\/ul>\n<h2 id=\"section_11\">11. Conclusion<\/h2>\n<p>Version control systems help to fulfill one of the dreams of every developer: having identified each point of the entire history of a project, being able to return to any point at any time. The VCS we have seen in this guide is Git, the preferred by the software developer community.<\/p>\n<p>After reading this guide, if it&#8217;s your first time with Git, you will probably be thinking how couldn&#8217;t you live without Git until today.<\/p>\n<h2 id=\"section_12\">12. Resources<\/h2>\n<p>The best resource possible is Pro Git (2nd edition), by Scott Chacon and Ben Straub, which covers almost every topic about Git. You can read it free at <a href=\"https:\/\/git-scm.com\/book\/en\/v2\">Git official page<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Git is, without any doubt, the most popular version control system. Ironically, there are other version control systems easier to learn and to use, but, despite that, Git is the favorite option for developers, which is quite clarifying about the powerfulness of Git. This guide will cover all the topics needed to know in order &hellip;<\/p>\n","protected":false},"author":1069,"featured_media":118,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[334,450],"class_list":["post-58367","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software-development","tag-git","tag-version-control"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Git Tutorial - The Ultimate Guide (PDF Download) - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Check out our Git Tutorial! After reading this guide you will be thinking how could you live without Git! You can also download our FREE Git Ultimate Guide!\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Git Tutorial - The Ultimate Guide (PDF Download) - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Check out our Git Tutorial! After reading this guide you will be thinking how could you live without Git! You can also download our FREE Git Ultimate Guide!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2016-07-25T07:00:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-08T10:27:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/git-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Toni\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Toni\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"34 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html\"},\"author\":{\"name\":\"Toni\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cffd0d975cb00647f3c0788a67a82a0d\"},\"headline\":\"Git Tutorial &#8211; The Ultimate Guide (PDF Download)\",\"datePublished\":\"2016-07-25T07:00:28+00:00\",\"dateModified\":\"2023-12-08T10:27:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html\"},\"wordCount\":7083,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/git-logo.jpg\",\"keywords\":[\"Git\",\"Version Control\"],\"articleSection\":[\"Software Development\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html\",\"name\":\"Git Tutorial - The Ultimate Guide (PDF Download) - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/git-logo.jpg\",\"datePublished\":\"2016-07-25T07:00:28+00:00\",\"dateModified\":\"2023-12-08T10:27:46+00:00\",\"description\":\"Check out our Git Tutorial! After reading this guide you will be thinking how could you live without Git! You can also download our FREE Git Ultimate Guide!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/git-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/git-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2016\\\/07\\\/git-tutorial.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Software Development\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/software-development\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Git Tutorial &#8211; The Ultimate Guide (PDF Download)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/cffd0d975cb00647f3c0788a67a82a0d\",\"name\":\"Toni\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c1661474c78b4757355b8beef9ab1d14f490ee3a3e67392f4e618d36643d4c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c1661474c78b4757355b8beef9ab1d14f490ee3a3e67392f4e618d36643d4c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c1661474c78b4757355b8beef9ab1d14f490ee3a3e67392f4e618d36643d4c?s=96&d=mm&r=g\",\"caption\":\"Toni\"},\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/julen-pardo\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Git Tutorial - The Ultimate Guide (PDF Download) - Java Code Geeks","description":"Check out our Git Tutorial! After reading this guide you will be thinking how could you live without Git! You can also download our FREE Git Ultimate Guide!","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html","og_locale":"en_US","og_type":"article","og_title":"Git Tutorial - The Ultimate Guide (PDF Download) - Java Code Geeks","og_description":"Check out our Git Tutorial! After reading this guide you will be thinking how could you live without Git! You can also download our FREE Git Ultimate Guide!","og_url":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2016-07-25T07:00:28+00:00","article_modified_time":"2023-12-08T10:27:46+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/git-logo.jpg","type":"image\/jpeg"}],"author":"Toni","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Toni","Est. reading time":"34 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html"},"author":{"name":"Toni","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cffd0d975cb00647f3c0788a67a82a0d"},"headline":"Git Tutorial &#8211; The Ultimate Guide (PDF Download)","datePublished":"2016-07-25T07:00:28+00:00","dateModified":"2023-12-08T10:27:46+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html"},"wordCount":7083,"commentCount":5,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/git-logo.jpg","keywords":["Git","Version Control"],"articleSection":["Software Development"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html","url":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html","name":"Git Tutorial - The Ultimate Guide (PDF Download) - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/git-logo.jpg","datePublished":"2016-07-25T07:00:28+00:00","dateModified":"2023-12-08T10:27:46+00:00","description":"Check out our Git Tutorial! After reading this guide you will be thinking how could you live without Git! You can also download our FREE Git Ultimate Guide!","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/git-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/git-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2016\/07\/git-tutorial.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Software Development","item":"https:\/\/www.javacodegeeks.com\/category\/software-development"},{"@type":"ListItem","position":3,"name":"Git Tutorial &#8211; The Ultimate Guide (PDF Download)"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/cffd0d975cb00647f3c0788a67a82a0d","name":"Toni","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/21c1661474c78b4757355b8beef9ab1d14f490ee3a3e67392f4e618d36643d4c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/21c1661474c78b4757355b8beef9ab1d14f490ee3a3e67392f4e618d36643d4c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/21c1661474c78b4757355b8beef9ab1d14f490ee3a3e67392f4e618d36643d4c?s=96&d=mm&r=g","caption":"Toni"},"url":"https:\/\/www.javacodegeeks.com\/author\/julen-pardo"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/58367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=58367"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/58367\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/118"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=58367"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=58367"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=58367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}