40,81 €
A series of practical recipes to simplify the Git learning experience and increase your productivity when using Git version control
Key Features
Book Description
Git is one of the most popular tools for versioning. Git Version Control Cookbook builds on the success of the previous edition and provides you with an up-to-date guide to solving problems related to versioning.
You'll start by learning about the Git data model and how it stores files and looks at commits. By using simple commands, you'll learn how to navigate through the database. Once you have accustomed yourself to the basics, you'll explore techniques to configure Git with comprehensive examples and configuration targets. You'll gain insights into improving your understanding of branches and recovery from mistakes — right from committing to a wrong branch to recovering lost commits or files. You'll then move on to discovering the features that Git rebase has to offer and use regular Git merge on other branches. You'll explore Git notes and learn how to utilize the update, list, and search commands. In addition to this, you'll learn how to extract metadata from repositories and automate your daily tasks using Git hooks. You'll then study in detail repository maintenance, patching, and offline sharing. By the end of the book, you'll have grasped various tips and tricks for everyday usage, while increasing your knowledge of Git providers, integrations, and clients.
What you will learn
Who this book is for
The Git Version Control Cookbook is for you if you are a developer or Build Release manager looking for a full-fledged practical guide that will take your Git knowledge to the next level. Basic knowledge of GNU tools and shell or bash scripting is needed.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 371
Veröffentlichungsjahr: 2018
Copyright © 2018 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Commissioning Editor: Aaron LazarAcquisition Editor: Shriram ShekharContent Development Editor: Pooja ParvatkarTechnical Editor: Subhalaxmi NadarCopy Editor: Safis EditingProject Coordinator: Ulhas KambaliProofreader: Safis EditingIndexer: Rekha NairGraphics: Tania DuttaProduction Coordinator: Deepika Naik
First published: July 2014 Second edition: July 2018
Production reference: 1240718
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-78913-754-5
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Kenneth Geisshirt is a chemist, by education, and a strong free-software advocate. He spent his Christmas holidays in 1992 installing SLS Linux, and GNU/Linux has been his favorite operating system ever since. Currently, he does consultancy work in fields such as scientific computing and Linux clusters. He lives in Copenhagen, Denmark, with his partner and their two children.
Emanuele Zattin is the Continuous Integration Specialist at Realm Inc. with experience in software development and design. He is respected for his work in designing and developing a CM Synergy to Git history conversion tool and rolling out Git-Gerrit-Jenkins in several Nokia divisions.
Aske Olsson has more than 14 years of experience in the software industry. As an electrical engineer, he has been using every tool available for development, from a soldering iron over Assembly, C, Java Groovy, Python and various DSLs for programming to different SCMs and build-, CI- and issue-tracking systems. He has worked for Nokia for 6 years and, currently, works at Keylane. Aske has experience with Git; he has been teaching Git in regular training sessions, from basic Git to advanced usage.
Rasmus Voss has been working with continuous integration, continuous delivery, automatic testing, and DevOps, in various industries. He has always strived to ensure that where developers, testers, project leaders, and managers can work with the system instead of against the system. Typically, the processes and solutions he develops are clear, precise, and well documented, with relevant feedback to all parts of the software development process.
Chen Mulong has been working on mobile development for over 10 years. He has coded for all different kinds of mobile devices, from the ancient feature phone platform, which is made of plain C, to the modern smart device platform, Android. Open source is his first choice for solving daily problems.
He has experienced the chaos of being part of a team of 100+ developers and the peace brought about by excellent SCM tools. He loves to tell others how good Git is at making every developer's life easier. He now works as a freelancer in Beijing, China.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Git Version Control Cookbook Second Edition
Packt Upsell
Why subscribe?
PacktPub.com
Contributors
About the authors
About the reviewer
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the color images
Conventions used
Sections
Getting ready
How to do it…
How it works…
There's more…
See also
Get in touch
Reviews
Navigating Git
Introduction
Git's objects
Getting ready
How to do it...
The commit object
The tree object
The blob object
The branch object
The tag object
How it works...
There's more...
The three stages
Getting ready
How to do it...
How it works...
See also
Viewing the DAG
Getting ready
How to do it...
How it works...
Extracting fixed issues
Getting ready
How to do it...
How it works...
There's more...
Getting a list of the changed files
Getting ready
How to do it...
How it works...
There's more...
See also
Viewing the history with gitk
Getting ready
How to do it...
How it works...
There's more...
Finding commits in the history
Getting ready
How to do it...
How it works...
There's more...
Searching through the history code
Getting ready
How to do it...
How it works...
There's more...
Configuration
Introduction
Configuration targets
Getting ready
How to do it...
How it works...
There's more...
Querying the existing configuration
Getting ready
How to do it...
How it works...
There's more...
Templates
Getting ready
How to do it...
How it works...
A .git directory template
Getting ready
How to do it...
How it works...
See also
A few configuration examples
Getting ready
How to do it...
Rebase and merge setup
Expiry of objects
Autocorrect
How it works...
There's more...
Git aliases
Getting ready
How to do it...
How it works...
There's more...
The refspec exemplified
Getting ready
How to do it...
How it works...
Branching, Merging, and Options
Introduction
Managing your local branches
Getting ready
How to do it...
How it works...
There's more...
Branches with remotes
Getting ready
How to do it...
There's more...
Forcing a merge commit
Getting ready
How to do it...
There's more...
Using git reuse recorded resolution (rerere) to merge Git conflicts
How to do it...
There's more...
Compute the difference between branches
Getting ready
How to do it...
Orphan branches
Getting ready
How to do it...
There's more...
Rebasing Regularly and Interactively, and Other Use Cases
Introduction
Rebasing commits to another branch
Getting ready
How to do it...
How it works...
Continuing a rebase with merge conflicts
How to do it...
How it works...
There's more...
Rebasing selected commits interactively
Getting ready
How to do it...
There's more...
Squashing commits using an interactive rebase
Getting ready
How to do it...
There's more...
Changing the author of commits using a rebase
Getting ready
How to do it...
How it works...
Autosquashing commits
Getting ready
How to do it...
There's more...
Storing Additional Information in Your Repository
Introduction
Adding your first Git note
Getting ready
How to do it...
There's more...
Separating notes by category
Getting ready
How to do it...
How it works...
Retrieving notes from the remote repository
Getting ready
How to do it...
How it works...
Pushing Git notes to a remote repository
How to do it...
There's more...
Tagging commits in the repository
Getting ready
How to do it...
There's more...
Extracting Data from the Repository
Introduction
Extracting the top contributor
Getting ready
How to do it...
There's more...
Finding bottlenecks in the source tree
Getting ready
How to do it...
There's more...
Grepping the commit messages
Getting ready
How to do it...
The contents of the releases
How to do it...
How it works...
Finding what has been achieved in the repository in the last period
How to do it...
How it works...
There's more...
Enhancing Your Daily Work with Git Hooks, Aliases, and Scripts
Introduction
Using a branch description in a commit message
Getting ready
How to do it...
Creating a dynamic commit message template
Getting ready
How to do it...
There's more...
Using external information in a commit message
Getting ready
How to do it...
Preventing the push of specific commits
Getting ready
How to do it...
There's more...
Configuring and using Git aliases
How to do it...
How it works...
Configuring and using Git scripts
How to do it...
Setting up and using a commit template
Getting ready
How to do it...
Recovering from Mistakes
Introduction
Undo – Remove a commit completely
Getting ready
How to do it...
How it works...
Undo – Remove a commit and retain changes to files
Getting ready
How to do it...
How it works...
Undo – Remove a commit and retain changes in the staging area
Getting ready
How to do it...
How it works...
Undo – Working with a dirty area
Getting ready
How to do it...
How it works...
Redo – Recreate the latest commit with new changes
Getting ready
How to do it...
How it works...
There's more...
Revert – Undo the changes introduced by a commit
Getting ready
How to do it...
How it works...
There's more...
Reverting a merge
Getting ready
How to do it...
How it works...
There's more...
See also
Viewing past Git actions with git reflog
Getting ready
How to do it...
How it works...
Finding lost changes with git fsck
Getting ready
How to do it...
How it works...
Repository Maintenance
Introduction
Pruning remote branches
Getting ready
How to do it...
How it works...
There's more...
Running garbage collection manually
Getting ready
How to do it...
How it works...
Turning off automatic garbage collection
Getting ready
How to do it...
Splitting a repository
Getting ready
How to do it...
How it works...
There's more...
Rewriting history – changing a single file
Getting ready
How to do it...
How it works...
Creating a backup of your repositories as mirror repositories
Getting ready
How to do it...
How it works...
There's more...
A quick "how-to" submodule
Getting ready
How to do it...
There's more...
Subtree merging
Getting ready
How to do it...
How it works...
See also
Submodule versus subtree merging
Patching and Offline Sharing
Introduction
Creating patches
Getting ready
How to do it...
How it works...
There's more...
Creating patches from branches
Getting ready
How to do it...
How it works...
There's more...
Applying patches
Getting ready
How to do it...
How it works...
There's more...
Sending patches
Getting ready
How to do it...
How it works...
There's more...
Creating Git bundles
Getting ready
How to do it...
How it works...
Using a Git bundle
Getting ready
How to do it...
There's more...
Creating archives from a tree
Getting ready
How to do it...
There's more...
Tips and Tricks
Introduction
Using git stash
Getting ready
How to do it...
How it works...
There's more...
Saving and applying stashes
Getting ready
How to do it...
There's more...
Debugging with git bisect
Getting ready
How to do it...
There's more...
Using the blame command
Getting ready
How to do it...
There's more...
Coloring the UI in the prompt
Getting ready
How to do it...
There's more...
Autocompletion
Getting ready
Linux
Mac
Windows
How to do it...
How it works...
There's more...
Bash prompt with status information
Getting ready
How to do it...
How it works...
There's more...
See also
More aliases
Getting ready
How to do it...
Interactive add
Getting ready
How to do it...
There's more...
Interactive add with Git gui
Getting ready
How to do it...
Ignoring files
Getting ready
How to do it...
There's more...
See also
Showing and cleaning ignored files
Getting ready
How to do it...
There's more...
Git Providers, Integrations, and Clients
Introduction
Setting up an organization at GitHub
Getting ready
How to do it...
How it works...
There's more...
See also
Creating a repository at GitHub
Getting ready
How to do it...
How it works...
There's more...
Adding templates for issues and pull requests
Getting ready
How to do it...
How it works...
Creating a GitHub API key
Getting ready
How to do it...
How it works...
See also
Using GitHub to authenticate at Jenkins
Getting ready
How to do it...
How it works...
There's more...
See also
Triggering Jenkins builds
Getting ready
How to do it...
How it works...
There's more...
See also
Using Jenkinsfiles
Getting ready
How to do it...
How it works...
There's more...
See also
Other Books You May Enjoy
Leave a review - let other readers know what you think
Git is increasingly becoming the de facto standard for Source Control Management (SCM) in modern software development.
Originally developed by Linus Torvalds as an SCM system for the Linux kernel to replace the proprietary SCM BitKeeper, Git has since conquered most of the open source world and is also used by lots of organizations for their private/proprietary projects.
This book is designed to give you practical recipes for everyday Git usage. The recipes can be used directly or as inspiration. The book will cover the Git data model through practical recipes and in-depth explanations so you get a deeper understanding of the internal workings of Git. This book will show you the following topics:
Working with the history. With Git, all the history is stored locally. You cansearch through the history, view the history, find the last commit on a certain branch, and more.Using branches effectively with options and strategies to push, pull, and merge them.Storing and extracting additional metadata in the Git repository.Disaster recovery: local and global.Git Version Control Cookbookgives you precise, step-by-step instructions for various common and uncommon Git operations. The book will make your daily work with Git easier by providingrecipes for common issues, useful tips and tricks, and in-depth clarifications of why andhow they work.
This book targets developers, professional build/release managers, and DevOps practitioners who want a practical guide for the next level of Git. Starting with the Git data model and advancing through branching to metadata and hooks, all through an easy-to-read recipe structure, the transition from simple, everyday use cases to advanced repository handling is smooth. The book can be easily read and understood by readers from the target audience. You need basic knowledge of common GNU/Linux tools and Shell/Bash scripting to get the most from this book.
Chapter 1,Navigating Git, shows how Git stores files and commits. Examples will visually showyou the data model and how to navigate the history and database with simple commands.
Chapter 2,Configuration, shows how a lot can be configured in Git, how configuration targets are set, the different configuration levels, and some useful targets.
Chapter 3,Branching, Merging, and Options, will give you a deeper understanding of branching and the options for easy push/pull targets. It also shows you the different merge strategies and some tips on how to record merge resolutions.
Chapter 4,Rebasing Regularly and Interactively, and Other Use Cases, shows you how rebasing can be used instead of merging, along with a lot of other use cases of rebasing, such as cleaning up the history before publishing, and testing single commits.
Chapter 5,Storing Additional Information in Your Repository, takes you on a tour of Git notes. It will show you how to tie additional information to a commit, and how to use and see this information again.
Chapter 6,Extracting Data from the Repository, shows you how to extract statistics and other metadata from the repository.
Chapter 7,Enhancing Your Daily Work with Git Hooks, Aliases, and Scripts, contains a collection of recipes that will help you automate much of the tedious daily work.
Chapter 8,Recovering from Mistakes, walks you through several recovery scenarios, from local undo, to where-is-my-old-commit, to global recovery scenarios.
Chapter 9,Repository Maintenance, is a collection of recipes that relate to the maintenance and management of repositories, from forcing garbage collection, over-splitting, and joining repositories, to completely rewriting history.
Chapter 10,Patching and Offline Sharing, shows you how to work offline with Git and sharethe work by means other than pushing and pulling.
Chapter 11,Tips and Tricks, is a collection of recipes that cover various topics, from simple tips to displaying the current branch in your prompt to advanced Git tools, such as bisect and stash.
Chapter 12, Git Providers, Integrations, and Clients, introduces the largest Git-hosting site, GitHub. Moreover, the chapter will discuss how to integrate Jenkins for automated builds and tests.
To follow and recreate the recipes from this book, you will need a computer preferably running a *nix operating system. You will need Git installed, preferably Git Version 2.x or later.
If you are a Windows user, we recommend the Git Extensions package, which ships both a graphical and textual (Bash) Git interface. The latter is required for the recipes in this book.
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/GitVersionControlCookbookSecondEdition_ColorImages.pdf.
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "The most recent commit is the 3061dc6 Adds Java version of 'hello world'commit."
Any command-line input or output is written as follows:
$ git checkout master && git reset --hard b14a939
Bold: Indicates a new term, an important word, or words that you see onscreen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Select System info from the Administration panel."
In this book, you will find several headings that appear frequently (Getting ready, How to do it..., How it works..., There's more..., and See also).
To give clear instructions on how to complete a recipe, use these sections as follows:
This section tells you what to expect in the recipe and describes how to set up any software or anypreliminary settings required for the recipe.
This section contains the steps required to follow the recipe.
This section usually consists of a detailed explanation of what happened in the previous section.
This section consists of additional information about the recipe in order to make you more knowledgeable about the recipe.
This section provides helpful links to other useful information for the recipe.
Feedback from our readers is always welcome.
General feedback: Email [email protected] and mention the book title in the subject of your message. If you have questions about any aspect of this book, please email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packtpub.com.
In this chapter, we will cover the following topics:
Git's objects
The three stages
Viewing the DAG
Extracting fixed issues
Getting a list of the changed files
Viewing the history with gitk
Finding commits in the history
Searching through the history code
In this chapter, we will take a look at Git's data model. We will learn how Git references its objects and how the history is recorded. We will learn how to navigate the history, from finding certain text snippets in commit messages, to the introducing a particular string in the code.
The data model of Git is different from other common version control systems (VCSs) in the way Git handles its data. Traditionally, a VCS will store its data as an initial file, followed by a list of patches for each new version of the file:
Git is different: Instead of the regular file and patches list, Git records a snapshot of all the files tracked by Git and their paths relative to the repository root—that is, the files tracked by Git in the filesystem tree. Each commit in Git records the full tree state. If a file does not change between commits, Git will not store the file again. Instead, Git stores a link to the file. This is shown in the diagram below where you see how the files will be after every commit/version.
This is what makes Git different from most other VCSs, and, in the following chapters, we will explore some of the benefits of this powerful model.
The way Git references files and directories is directly built into the data model. In short, the Git data model can be summarized as shown in the following diagram:
The commit object points to the root tree. The root tree points to subtrees and files.
Branches and tags point to a commit object and the HEAD object points to the branch that is currently checked out. So, for every commit, the full tree state and snapshot are identified by the root tree.
Now, since you know that Git stores every commit as a full tree state or snapshot, let's take a closer look at the object's Git store in the repository.
Git's object storage is a key-value storage, the key being the ID of the object and the value being the object itself. The key is an SHA-1 hash of the object, with some additional information, such as size. There are four types of objects in Git, as well as branches (which are not objects, but which are important) and the special HEAD pointer that refers to the branch/commit currently being checked out. The four object types are as follows:
Files, or blobs as they are also called in the Git context
Directories, or trees in the Git context
Commits
Tags
We will start by looking at the most recent commit object in the repository we just cloned, keeping in mind that the special HEAD pointer points to the branch that is currently being checked out.
To view the objects in the Git database, we first need a repository to be examined. For this recipe, we will clone an example repository in the following location:
$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition.git
$ cd
Git-Version-Control-Cookbook-Second-Edition
Now you are ready to look at the objects in the database. We will start by looking first at the commit object, followed by the trees, the files, and finally, the branches and tags.
Let's take a closer look at the object's Git stores in the repository.
The Git's specialHEAD object always points to the current snapshot/commit, so we can use that as the target for our request of the commit that we want to have a look at:
$ git cat-file -p HEAD
tree 34fa038544bcd9aed660c08320214bafff94150b
parent 5c662c018efced42ca5e9cce709787c40a849f34
author John Doe <[email protected]> 1386933960 +0100
committer John Doe <[email protected]> 1386941455 +0100
This is the subject line of the commit message. It should be followed by a blank line and then the body, which is this text. Here, you can use multiple paragraphs to explain your commit. It's like an email with a subject and a body to try to attract people's attention to the subject.
The cat-file command with the -p option prints the object given on the command line; in this case, HEAD, points to master, which, in turn, points to the most recent commit on the branch.
We can now see the commit object, consisting of the root tree (tree), the parent commit object's ID (parent), the author and timestamp information (author), the committer and timestamp information (committer), and the commit message.
To see the tree object, we can run the same command on the tree, but with the tree ID (34fa038544bcd9aed660c08320214bafff94150b) as the target:
$ git cat-file -p 34fa038544bcd9aed660c08320214bafff94150b
100644 blob f21dc2804e888fee6014d7e5b1ceee533b222c15 README.md
040000 tree abc267d04fb803760b75be7e665d3d69eeed32f8 a_sub_directory
100644 blob b50f80ac4d0a36780f9c0636f43472962154a11a another-file.txt
100644 blob 92f046f17079aa82c924a9acf28d623fcb6ca727 cat-me.txt
100644 blob bb2fe940924c65b4a1cefcbdbe88c74d39eb23cd hello_world.c
We can also specify that we want the tree object from the commit pointed to by HEAD by specifying git cat-file -p HEAD^{tree}, which would give the same results as the previous command. The special notation HEAD^{tree} means that from the reference given, HEAD recursively dereferences the object at the reference until a tree object is found.
The first tree object is the root tree object found from the commit pointed to by the master branch, which is pointed to by HEAD. A generic form of the notation is <rev>^<type>, and will return the first object of <type>, searching recursively from <rev>.
From the tree object, we can see what it contains: the file type/permissions, type (tree/blob), ID, and pathname:
Type/
Permissions
Type
ID/SHA-1
Pathname
100644
blob
f21dc2804e888fee6014d7e5b1ceee533b222c15
README.md
040000
tree
abc267d04fb803760b75be7e665d3d69eeed32f8
a_sub_directory
100644
blob
b50f80ac4d0a36780f9c0636f43472962154a11a
another-file.txt
100644
blob
92f046f17079aa82c924a9acf28d623fcb6ca727
cat-me.txt
100644
blob
bb2fe940924c65b4a1cefcbdbe88c74d39eb23cd
hello-world.c
Now, we can investigate the blob (file) object. We can do this using the same command, giving the blob ID as the target for the cat-me.txt file:
$ git cat-file -p 92f046f17079aa82c924a9acf28d623fcb6ca727
The content of the file is cat-me.txt.
Not really that exciting, huh?
This is simply the content of the file, which we can also get by running a normal cat cat-me.txt command. So, the objects are tied together, blobs to trees, trees to other trees, and the root tree to the commit object, all connected by the SHA-1 identifier of the object.
The branch object is not really like any other Git objects; you can't print it using the cat-file command as we can with the others (if you specify the -p pretty print, you'll just get the commit object it points to), as shown in the following code:
$ git cat-file master
usage: git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>
or: git cat-file (--batch|--batch-check) < <list_of_objects>
<type> can be one of: blob, tree, commit, tag.
...
$ git cat-file -p master
tree 34fa038544bcd9aed660c08320214bafff94150b
parent a90d1906337a6d75f1dc32da647931f932500d83
...
Instead, we can take a look at the branch inside the .git folder where the whole Git repository is stored. If we open the text file .git/refs/heads/master, we can actually see the commit ID that the master branch points to. We can do this using cat, as follows:
$ cat .git/refs/heads/master
13dcada077e446d3a05ea9cdbc8ecc261a94e42d
We can verify that this is the latest commit by running git log -1:
$ git log -1
commit 34acc370b4d6ae53f051255680feaefaf7f7850d (HEAD -> master, origin/master, origin/HEAD)
Author: John Doe <[email protected]>
Date: Fri Dec 13 12:26:00 2013 +0100
This is the subject line of the commit message
...
We can also see that HEAD is pointing to the active branch by using cat with the .git/HEAD file:
$ cat .git/HEAD
ref: refs/heads/master
The branch object is simply a pointer to a commit, identified by its SHA-1 hash.
The last object to be analyzed is the tag object. There are three different kinds of tag: a lightweight (just a label) tag, an annotated tag, and a signed tag. In the example repository, there are two annotated tags:
$ git tag
v0.1
v1.0
Let's take a closer look at the v1.0 tag:
$ git cat-file -p v1.0
object f55f7383b57ad7c11cf56a7c55a8d738af4741ce
type commit
tag v1.0
tagger John Doe <[email protected]> 1526017989 +0200
We got the hello world C program merged, let's call that a release 1.0
As you can see, the tag consists of an object—which, in this case, is the latest commit on the master branch—the object's type (commits, blobs, and trees can be tagged), the tag name, the tagger and timestamp, and finally the tag message.
The Git command git cat-file -p will print the object given as an input. Normally, it is not used in everyday Git commands, but it is quite useful to investigate how it ties the objects together.
We can also verify the output of git cat-file by rehashing it with the Git command git hash-object; for example, if we want to verify the commit object at HEAD (34acc370b4d6ae53f051255680feaefaf7f7850d), we can run the following command:
$ git cat-file -p HEAD | git hash-object -t commit --stdin
13dcada077e446d3a05ea9cdbc8ecc261a94e42d
If you see the same commit hash as HEAD pointing towards you, you can verify whether it is correct using git log -1.
There are many ways to see the objects in the Git database. The git ls-tree command can easily show the content of trees and subtrees, and git show can show the Git objects, but in a different way.
We have seen the different objects in Git, but how do we create them? In this example, we'll see how to create a blob, tree, and commit object in the repository. We'll also learn about the three stages of creating a commit.
We'll use the same Git-Version-Control-Cookbook-Second-Edition repository that we saw in the last recipe:
$ git clone https://github.com/PacktPublishing/Git-Version-Control-Cookbook-Second-Edition.git
$ cd
Git-Version-Control-Cookbook-Second-Edition
First, we'll make a small change to the file and check
git status
:
$ echo "Another line" >> another-file.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: another-file.txt
no changes added to commit (use "git add" and/or "git commit -a")
This, of course, just tells us that we have modified another-file.txt and we need to use git add to stage it.
Let's add the
another-file.txt
file and run
git status
again:
$ git add another-file.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: another-file.txt
The file is now ready to be committed, just as you have probably seen before. But what happens during the add command? The add command, generally speaking, moves files from the working directory to the staging area; however, this is not all that actually happens, though you don't see it. When a file is moved to the staging area, the SHA-1 hash of the file is created and the blob object is written to Git's database. This happens every time a file is added, but if nothing changes for a file, it means that it is already stored in the database. At first, this might seem that the database will grow quickly, but this is not the case. Garbage collection kicks in at times, compressing, and cleaning up the database and keeping only the objects that are required.
We can edit the file again and run
git status
:
$ echo 'Whoops almost forgot this' >> another-file.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: another-file.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: another-file.txt
Now, the file shows up in both the Changes to be committed and Changes not staged for commit sections. This looks a bit weird at first, but there is, of course, a reason for this. When we added the file the first time, the content of it was hashed and stored in Git's database. The changes arising from the second change to the file have not yet been hashed and written to the database; it only exists in the working directory. Therefore, the file shows up in both the Changes to be committed and Changes not staged for commit sections; the first change is ready to be committed, the second is not. Let's also add the second change:
$ git add another-file.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: another-file.txt
Now, all the changes we have made to the file are ready to be committed, and we can record a commit:
$ git commit -m 'Another change to another file'
[master 99fac83] Another change to another file
1 file changed, 2 insertions(+)
As we learned previously, the add command creates the blob, tree, and commit objects; however, they are also created when we run the commit command. We can view these objects using the cat-file command, as we saw in the previous recipe:
$ git cat-file -p HEAD
tree 162201200b5223d48ea8267940c8090b23cbfb60
parent 13dcada077e446d3a05ea9cdbc8ecc261a94e42d
author John Doe <[email protected]> 1524163792 +0200
committer John Doe <[email protected]> 1524163792 +0200
Making changes to another file.
The root-tree object from the commit is as follows:
$ git cat-file -p HEAD^{tree}
100644 blob f21dc2804e888fee6014d7e5b1ceee533b222c15 README.md
040000 tree abc267d04fb803760b75be7e665d3d69eeed32f8 a_sub_directory
100644 blob 35d31106c5d6fdb38c6b1a6fb43a90b183011a4b another-file.txt
100644 blob 92f046f17079aa82c924a9acf28d623fcb6ca727 cat-me.txt
100644 blob bb2fe940924c65b4a1cefcbdbe88c74d39eb23cd hello_world.c
From the previous recipe, we know that the SHA-1 of the root tree was 34fa038544bcd9aed660c08320214bafff94150b and the SHA-1 of the another-file.txt file was b50f80ac4d0a36780f9c0636f43472962154a11a, and, as expected, they changed in our latest commit when we updated the another-file.txt file. We added the same file, another-file.txt, twice before we created the commit, recording the changes to the history of the repository. We also learned that the add command creates a blob object when called. So, in the Git database, there must have been an object similar to the content of another-file.txt the first time we added the file to the staging area. We can use the git fsck command to check for dangling objects—that is, objects that are not referred to by other objects or references:
$ git fsck --dangling
Checking object directories: 100% (256/256), done.
dangling blob ad46f2da274ed6c79a16577571a604d3281cd6d9
Let's check the content of the blob using the following command:
$ git cat-file -p ad46f2da274ed6c79a16577571a604d3281cd6d9
This is just another file
Another line
The blob was, as expected, similar to the content of another-file.txt when we added it to the staging area the first time.
The following diagram describes the tree stages and the commands used to move between the stages:
For more examples and information on the cat-file and fsck commands, please consult the Git documentation at https://git-scm.com/docs/git-cat-file and https://git-scm.com/docs/git-fsck.
The history in Git is formed from the commit objects; as development advances, branches are created and merged, and the history will create a directed acyclic graph, the DAG, because of the way that Git ties a commit to its parent commit. The DAG makes it easy to see the development of a project based on the commits.
Please note that the arrows in the following diagram are dependency arrows, meaning that each commit points to its parent commit(s), which is why the arrows point in the opposite direction to the normal flow of time:
You can view the history (the DAG) in Git by using its git log command. There are also a number of visual Git tools that can graphically display the history. This section will show some features of git log.
We will use the example repository from the last section and ensure that the master branch is pointing to 34acc37:
$ git checkout master && git reset --hard 34acc37
In the previous command, we only use the first seven characters (34acc37) of the commit ID; this is fine as long as the abbreviated ID that is used is unique in the repository.
The simplest way to see the history is to use the
git log
command; this will display the history in reverse chronological order. The output is paged through
less
and can be further limited, for example, by providing only the number of commits in the history to be displayed:
$ git log -3
This will display the following result:
commit 34acc370b4d6ae53f051255680feaefaf7f7850d
Author:
John Doe <[email protected]
>
Date: Fri Dec 13 12:26:00 2013 +0100
This is the subject line of the commit message.
It should be followed by a blank line then the body, which is this text. Here
you can have multiple paragraphs etc. and explain your commit. It's like an
email with subject and body, so try to get people's attention in the subject
commit a90d1906337a6d75f1dc32da647931f932500d83
Author:
John Doe <[email protected]
>
Date: Fri Dec 13 12:17:42 2013 +0100
Instructions for compiling hello_world.c
commit 485884efd6ac68cc7b58c643036acd3cd208d5c8
Merge: 44f1e05 0806a8b
Author: John Doe <[email protected]>
Date: Fri Dec 13 12:14:49 2013 +0100
Merge branch 'feature/1'
Adds a hello world C program.
By default,
git log
prints the commit, author's name and email ID, timestamp, and the commit message. However, the information isn't very graphical, especially if you want to see branches and merges. To display this information and limit some of the other data, you can use the following options with
git log
:
$ git log --decorate --graph --oneline --all
The previous command will show one commit per line (
--oneline
), identified by its abbreviated commit ID, and the commit message subject. A graph will be drawn between the commits depicting their dependency (
--graph
). The
--decorate
option shows the branch names after the abbreviated commit ID, and the
--all
option shows all the branches, instead of just the current one(s):
$ git log --decorate --graph --oneline --all
* 34acc37 (HEAD, tag: v1.0, origin/master, origin/HEAD, master) This is the sub...
* a90d190 Instructions for compiling hello_world.c
* 485884e Merge branch 'feature/1'
...
This output, however, gives neither the timestamp nor the author information, because of the way the --oneline option formats the output.
Fortunately, the
log
command gives us the ability to create our own output format. So, we can make a history view similar to the previous one. The colors are made with the
%C<color-name>text-be-colored%Creset
