Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
156 lines (138 sloc) 10 KB
% afterhours6.tex - Afer Hours Week 6
% Still need to fix nested lists :(
\chapter{After Hours Week 6}
\section{``Tug of war''}
\subsection{Taking the push with the pull}
We have spoken at fairly great length about how remote repositories work.
We have seen how the \texttt{git remote} tool is used to create the various references to remote repositories, but we have no real understanding about what this means in terms of Git's internals.
Just in the same way a branch is a single file that contains a pointer to a reference, a remote repository has to be handled within Git somehow.
As it happens, Git again uses a reasonably simplistic design when creating \index{remote references}remote references.
To take a look at this in detail, we need to once again delve into the \texttt{.git} directory.
Seeing as our original repository does not contain any remotes for now, we are going to use our \texttt{coderepo-cl} folder as an example.
Hopefully, if you have been following the text, you have not deleted this directory yet.
If you have, do not worry, just follow the operations we completed in Week 6, or read on and use the text in the book.
If you remember, we created two clones of our original repository.
One of these was a simple clone called \texttt{coderepo-cl} and the other was a bare repository called \texttt{coderepo-bk}.
The \texttt{coderepo-cl} and the \texttt{coderepo-bk} repositories were both cloned from \texttt{coderepo}, but it was \texttt{coderepo-cl} that was configured to pull from one and push to the other.
Running a simple \texttt{git remote -v} command, confirms this configuration.
john@satsuki:~/coderepo-cl$ git remote -v
backup /home/john/coderepo-bk (fetch)
backup /home/john/coderepo-bk (push)
origin /home/john/coderepo (fetch)
origin /home/john/coderepo (push)
We can get even more information by running the \texttt{git remote show} tool with the remote name as a parameter.
john@satsuki:~/coderepo-cl$ git remote show origin
* remote origin
Fetch URL: /home/john/coderepo
Push URL: /home/john/coderepo
HEAD branch: master
Remote branches:
master tracked
wonderful tracked
zaney tracked
Local branches configured for 'git pull':
master merges with remote master
wonderful merges with remote wonderful
Local refs configured for 'git push':
master pushes to master (up to date)
wonderful pushes to wonderful (up to date)
How though, is this data set up and configured from within Git itself?
Looking at the \texttt{.git/config} file, we can see a glimpse of this.
john@satsuki:~/coderepo-cl$ cat .git/config
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = /home/john/coderepo
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "wonderful"]
remote = origin
merge = refs/heads/wonderful
[remote "backup"]
url = /home/john/coderepo-bk
fetch = +refs/heads/*:refs/remotes/backup/*
As you can see there are two relevant sections, these are the \texttt{remote} and \texttt{branch} stanzas.
The \texttt{remote} stanzas are there to define certain elements of the remote repository,
whilst the \texttt{branch} stanzas describe elements and settings for the branches that we are tracking.
Let us look at the relevant elements that we have set out in \texttt{config} file for each type of stanza.
We will start by looking at the \texttt{remote} \index{stanza}stanza. We have two settings here in our configuration.
The first is \texttt{url} and the second is \texttt{fetch}.
\index{settings!url}The \texttt{url} setting tells Git the location of the remote repository defined by the name outlined within the quotation marks.
In our example, the remote we first encounter is called \textbf{origin} and has a url of \texttt{/home/john/coderepo}.
\index{settings!fetch}You will notice that there is also a second setting called \texttt{fetch}.
This setting tells Git which branches, or HEADs we are interested in. In the default configuration, we ask Git to fetch all branch HEADs.
This also has an effect on which objects are downloaded.
Git will look at all of the branch HEADs and work backwards to find out which commit objects need to be downloaded.
In the \texttt{refs/} folder there are two other folders by default called \texttt{tags} and \texttt{remotes}.
With the default configuration as above, these references will not be fetched,
and commits that are only pointed to by these references will not be downloaded either.
\index{settings!branch}Looking at the \texttt{branch} settings, we can see that there are a few more settings here that describe how Git responds to certain commands when inside a certain branch.
In both the cases above, Git will automatically use remote of \textbf{origin} as the remote to use when performing operations.
This means that when we run a \texttt{git pull}, we do not have to specify a remote to pull from.
Obviously if we wanted to, we could change this and have \textbf{wonderful}, for example, update from a different remote repository.
\index{settings!merge}The last setting in this file that we will concern ourselves with is the \texttt{merge} setting.
When we are in the named branch, this setting defines the upstream version of the named branch and is used for merging and can affect pulling and rebasing too.
We can set these settings and any of the others in the \texttt{config} file manually,
using the \texttt{git config} tool, which we used in a previous chapter.
\section{``Referring to objects''}
\subsection{The Git spelling bee}
It is now most definitely time we spoke about other ways to represent commit hashes.
More details can be found about this in the Git manual, but it is definitely worth spending a few minutes looking at the ways in which we can specify objects in the repository.
As you have seen in previous chapters, we have used branch names, commits hashes and tags to specify commits, but it is also possibly to use a variety of other methods to do so.
We are going to use the \indexgit{rev-parse} command again to return us an object hash from our description of an object.
These descriptions are ways to \emph{spell} objects.
\item\index{sha1}\texttt{<SHA1>} - This is most common way to specify an object.
The \texttt{<SHA1>} is the 40 character identifier that Git generates for each object.
As you have seen before, we do not have to specify the entire SHA1 hash, just the beginning portion that is unique.
\item\index{refname}\texttt{<refname>} - We use this type of referencing a lot when checking out branches.
The \texttt{<refname>} is a symbolic name.
An example of this would be \textbf{master}, which actually refers to \textbf{refs/heads/master}, which you have seen in the \texttt{.git} directory.
HEAD is also a \texttt{<refname>}. In general, Git will search through a number of directories to find the \texttt{<refname>} that is being referred to;
\item \texttt{.git/<name>}
\item \texttt{refs/<name>}
\item \texttt{refs/tags/<refname>}
\item \texttt{refs/heads/<name>}
\item \texttt{refs/remotes/<name>}
\item \texttt{refs/remotes/<name>/HEAD}
So if we used \textbf{master} as our \texttt{<refname>}, Git would search in \texttt{.git} root directory first,
then into \texttt{refs}, followed by \texttt{refs/tags}, and finishing with \texttt{refs/heads}.
\item\index{date}\texttt{<refname>@\{date\}} - Now we find a more interesting way of specifying references.
We can use something like \textbf{master@\{yesterday\}}, to show us the closeset commit to match that date time.
There are more complicated date specifications we can use as well, such as \textbf{master@\{"last week"\}}, or \textbf{master@\{"3 hours 2 minutes and 10 seconds ago"\}}.
We can even put in a specific date and time like so; \textbf{master@\{"2011-02-26 14:30:00"\}}
\item\texttt{<refname>@\{<n>\}} - This curious definition returns the commit that \texttt{<refname>} referred to \texttt{<n>} times in the past.
It uses the \emph{reflog}, which has been discussed before, to discover what commit \texttt{<refname>} pointed to.
Be careful when using this reference. It does not mean the commit that \texttt{<refname>} pointed \texttt{<n>} commits ago in the tree.
If you have been doing resets and other things, these items show up in the \emph{reflog}.
\item\texttt{<rev>\textasciicircum<n>} - Is a way of asking Git to traverse an object for it's parents and so \texttt{<rev>} or \texttt{<rev>\textasciicircum 1} means the first parent of a commit object.
An example of this would be \texttt{master\textasciicircum2}.
\item\texttt{<rev>\textasciitilde<n>} - Is a way of asking Git to traverse an object for it's \texttt{<n>}th grand-parent, following only first parents.
This will take a little understanding and it is advised that you read the man page online for more information about what this really means.
\item\texttt{<rev>\textasciicircum\{/<text>\}} - This definition actually initiates a search for the youngest commit where the commit message matches the regular expression after the slash.
\texttt{master\textasciicircum\{/bug\}} is an example of the usage of this reference definition.
\item\texttt{<rev>:<path>} - This allows us to obtain the object hash for the file specified at the \texttt{<rev>}.
We could then use the \texttt{git show} command to view that file.
As an example \texttt{git show HEAD\textasciitilde 3:readme.txt} would show us the file \texttt{readme.txt} as it was three grandparents back from HEAD.
All of these are valid ways to refer to commits and in some cases objects and trees too.
Imagine a situation where you wanted to view a file called \texttt{readme.txt} that was three commits back from a tag of \texttt{v44}.
Using our new knowledge, we could use \texttt{git show v44\textasciitilde 3:readme.txt}.
There are several other ways of referring to commits, but these are out of the scope of this chapter.
If you would like more information, refer to the man page for \texttt{git rev-parse}.