Skip to content

Commit

Permalink
Merge pull request progit#199 from tacker66/sha-1
Browse files Browse the repository at this point in the history
Sha-1
  • Loading branch information
ben committed Dec 19, 2014
2 parents 0733e5a + e63b0fc commit f782ee5
Show file tree
Hide file tree
Showing 19 changed files with 48 additions and 49 deletions.
2 changes: 1 addition & 1 deletion book/03-git-branching/sections/rebasing.asc
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ It's pretty safe to assume that the other developer doesn't want `C4` and `C6` t

If you *do* find yourself in a situation like this, Git has some further magic that might help you out. If someone on your team force pushes changes that overwrite work that you've based work on, your challenge is to figure out what is yours and what they've rewritten.

It turns out that in addition to the commit SHA checksum, Git also calculates a checksum that is based just on the patch introduced with the commit. This is called a ``patch-id''.
It turns out that in addition to the commit SHA-1 checksum, Git also calculates a checksum that is based just on the patch introduced with the commit. This is called a ``patch-id''.

If you pull down work that was rewritten and rebase it on top of the new commits from your partner, Git can often successfully figure out what is uniquely yours and apply them back on top of the new branch.

Expand Down
2 changes: 1 addition & 1 deletion book/06-github/sections/2-contributing.asc
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ Now if Tony goes back and closes out the original Pull Request, we can see that
.Cross references rendered in a Pull Request.
image::images/mentions-03-closed.png[PR closed]

In addition to issue numbers, you can also reference a specific commit by SHA. You have to specify a full 40 character SHA, but if GitHub sees that in a comment, it will link directly to the commit. Again, you can reference commits in forks or other repositories in the same way you did with issues.
In addition to issue numbers, you can also reference a specific commit by SHA-1. You have to specify a full 40 character SHA-1, but if GitHub sees that in a comment, it will link directly to the commit. Again, you can reference commits in forks or other repositories in the same way you did with issues.

==== Markdown

Expand Down
4 changes: 2 additions & 2 deletions book/07-git-tools/sections/advanced-merging.asc
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ $ git show :2:hello.rb > hello.ours.rb
$ git show :3:hello.rb > hello.theirs.rb
----

If you want to get a little more hard core, you can also use the `ls-files -u` plumbing command to get the actual SHAs of the Git blobs for each of these files.
If you want to get a little more hard core, you can also use the `ls-files -u` plumbing command to get the actual SHA-1s of the Git blobs for each of these files.

[source,console]
----
Expand All @@ -166,7 +166,7 @@ $ git ls-files -u
100755 e85207e04dfdd5eb0a1e9febbc67fd837c44a1cd 3 hello.rb
----

The `:1:hello.rb` is just a shorthand for looking up that blob SHA.
The `:1:hello.rb` is just a shorthand for looking up that blob SHA-1.

Now that we have the content of all three stages in our working directory, we can manually fix up theirs to fix the whitespace issue and re-merge the file with the little-known `git merge-file` command which does just that.

Expand Down
2 changes: 1 addition & 1 deletion book/07-git-tools/sections/debugging.asc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The next two fields are values extracted from that commit–the author name and
After that come the line number and the content of the file.
Also note the `^4832fe2` commit lines, which designate that those lines were in this file’s original commit.
That commit is when this file was first added to this project, and those lines have been unchanged since.
This is a tad confusing, because now you’ve seen at least three different ways that Git uses the `^` to modify a commit SHA, but that is what it means here.
This is a tad confusing, because now you’ve seen at least three different ways that Git uses the `^` to modify a commit SHA-1, but that is what it means here.

Another cool thing about Git is that it doesn’t track file renames explicitly.
It records the snapshots and then tries to figure out what was renamed implicitly, after the fact.
Expand Down
12 changes: 6 additions & 6 deletions book/07-git-tools/sections/replace.asc
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ Git's objects are unchangeable, but it does provide an interesting way to preten

The `replace` command lets you specify an object in Git and say "every time you see this, pretend it's this other thing". This is most commonly useful for replacing one commit in your history with another one.

For example, let's say you have a huge code history and want to split your repository into one short history for new developers and one much longer and larger history for people interested in data mining. You can graft one history onto the other by `replace`ing the earliest commit in the new line with the latest commit on the older one. This is nice because it means that you don't actually have to rewrite every commit in the new history, as you would normally have to do to join them together (because the parentage effects the SHAs).
For example, let's say you have a huge code history and want to split your repository into one short history for new developers and one much longer and larger history for people interested in data mining. You can graft one history onto the other by `replace`ing the earliest commit in the new line with the latest commit on the older one. This is nice because it means that you don't actually have to rewrite every commit in the new history, as you would normally have to do to join them together (because the parentage effects the SHA-1s).

Let's try this out. Let's take an existing repository, split it into two repositories, one recent and one historical, and then we'll see how we can recombine them without modifying the recent repositories SHA values via `replace`.
Let's try this out. Let's take an existing repository, split it into two repositories, one recent and one historical, and then we'll see how we can recombine them without modifying the recent repositories SHA-1 values via `replace`.

We'll use a simple repository with five simple commits:

Expand Down Expand Up @@ -70,7 +70,7 @@ c1822cf first commit

It's useful in this case to create a base commit that has instructions on how to expand the history, so other developers know what to do if they hit the first commit in the truncated history and need more. So, what we're going to do is create an initial commit object as our base point with instructions, then rebase the remaining commits (four and five) on top of it.

To do that, we need to choose a point to split at, which for us is the third commit, which is `9c68fdc` in SHA-speak. So, our base commit will be based off of that tree. We can create our base commit using the `commit-tree` command, which just takes a tree and will give us a brand new, parentless commit object SHA back.
To do that, we need to choose a point to split at, which for us is the third commit, which is `9c68fdc` in SHA-speak. So, our base commit will be based off of that tree. We can create our base commit using the `commit-tree` command, which just takes a tree and will give us a brand new, parentless commit object SHA-1 back.

[source,console]
----
Expand All @@ -85,7 +85,7 @@ The `commit-tree` command is one of a set of commands that are commonly referred

image::images/replace3.png[]

OK, so now that we have a base commit, we can rebase the rest of our history on top of that with `git rebase --onto`. The `--onto` argument will be the SHA we just got back from `commit-tree` and the rebase point will be the third commit (the parent of the first commit we want to keep, `9c68fdc`):
OK, so now that we have a base commit, we can rebase the rest of our history on top of that with `git rebase --onto`. The `--onto` argument will be the SHA-1 we just got back from `commit-tree` and the rebase point will be the third commit (the parent of the first commit we want to keep, `9c68fdc`):

[source,console]
----
Expand Down Expand Up @@ -153,11 +153,11 @@ e146b5f fifth commit
c1822cf first commit
----

Cool, right? Without having to change all the SHAs upstream, we were able to replace one commit in our history with an entirely different commit and all the normal tools (`bisect`, `blame`, etc) will work how we would expect them to.
Cool, right? Without having to change all the SHA-1s upstream, we were able to replace one commit in our history with an entirely different commit and all the normal tools (`bisect`, `blame`, etc) will work how we would expect them to.

image::images/replace5.png[]

Interestingly, it still shows `81a708d` as the SHA, even though it's actually using the `c6e1e95` commit data that we replaced it with. Even if you run a command like `cat-file`, it will show you the replaced data:
Interestingly, it still shows `81a708d` as the SHA-1, even though it's actually using the `c6e1e95` commit data that we replaced it with. Even if you run a command like `cat-file`, it will show you the replaced data:

[source,console]
----
Expand Down
4 changes: 2 additions & 2 deletions book/07-git-tools/sections/reset.asc
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ That means HEAD will be the parent of the next commit that is created.
It's generally simplest to think of HEAD as the snapshot of *your last commit*.

In fact, it's pretty easy to see what that snapshot looks like.
Here is an example of getting the actual directory listing and SHA checksums for each file in the HEAD snapshot:
Here is an example of getting the actual directory listing and SHA-1 checksums for each file in the HEAD snapshot:

[source,console]
----
Expand Down Expand Up @@ -204,7 +204,7 @@ This actually sort of makes sense – HEAD is just a pointer, and you can't poin
But the Index and Working directory _can_ be partially updated, so reset proceeds with steps 2 and 3.

So, assume we run `git reset file.txt`.
This form (since you did not specify a commit SHA or branch, and you didn't specify `--soft` or `--hard`) is shorthand for `git reset --mixed HEAD file.txt`, which will:
This form (since you did not specify a commit SHA-1 or branch, and you didn't specify `--soft` or `--hard`) is shorthand for `git reset --mixed HEAD file.txt`, which will:

1. Move the branch HEAD points to _(skipped)_
2. Make the Index look like HEAD _(stop here)_
Expand Down
6 changes: 3 additions & 3 deletions book/07-git-tools/sections/revision-selection.asc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ They aren’t necessarily obvious but are helpful to know.
You can obviously refer to a commit by the SHA-1 hash that it’s given, but there are more human-friendly ways to refer to commits as well.
This section outlines the various ways you can refer to a single commit.

==== Short SHA
==== Short SHA-1

Git is smart enough to figure out what commit you meant to type if you provide the first few characters, as long as your partial SHA-1 is at least four characters long and unambiguous – that is, only one object in the current repository begins with that partial SHA-1.

Expand Down Expand Up @@ -60,7 +60,7 @@ a11bef0 first commit

Generally, eight to ten characters are more than enough to be unique within a project.

As an example, the Linux kernel, which is a pretty large project with over 450k commits and 3.6 million objects, has no two objects whose SHAs overlap more than the first 11 characters.
As an example, the Linux kernel, which is a pretty large project with over 450k commits and 3.6 million objects, has no two objects whose SHA-1s overlap more than the first 11 characters.

[NOTE]
.A SHORT NOTE ABOUT SHA-1
Expand Down Expand Up @@ -95,7 +95,7 @@ $ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1
----

If you want to see which specific SHA a branch points to, or if you want to see what any of these examples boils down to in terms of SHAs, you can use a Git plumbing tool called `rev-parse`.
If you want to see which specific SHA-1 a branch points to, or if you want to see what any of these examples boils down to in terms of SHA-1s, you can use a Git plumbing tool called `rev-parse`.
You can see <<_git_internals>> for more information about plumbing tools; basically, `rev-parse` exists for lower-level operations and isn’t designed to be used in day-to-day operations.
However, it can be helpful sometimes when you need to see what’s really going on.
Here you can run `rev-parse` on your branch.
Expand Down
4 changes: 2 additions & 2 deletions book/07-git-tools/sections/rewriting-history.asc
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ $ git log -4 --pretty=format:"%h %s"
f3cc40e changed my name a bit
----

Once again, this changes the SHAs of all the commits in your list, so make sure no commit shows up in that list that you’ve already pushed to a shared repository.
Once again, this changes the SHA-1s of all the commits in your list, so make sure no commit shows up in that list that you’ve already pushed to a shared repository.

==== The Nuclear Option: filter-branch

Expand Down Expand Up @@ -326,4 +326,4 @@ $ git filter-branch --commit-filter '
----

This goes through and rewrites every commit to have your new address.
Because commits contain the SHA-1 values of their parents, this command changes every commit SHA in your history, not just those that have the matching e-mail address.
Because commits contain the SHA-1 values of their parents, this command changes every commit SHA-1 in your history, not just those that have the matching e-mail address.
8 changes: 4 additions & 4 deletions book/07-git-tools/sections/submodules.asc
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ Automatic merge failed; fix conflicts and then commit the result.

So basically what has happened here is that Git has figured out that the two branches record points in the submodule's history that are divergent and need to be merged. It explains it as ``merge following commits not found'', which is confusing but we'll explain why that is in a bit.

To solve the problem, you need to figure out what state the submodule should be in. Strangely, Git doesn't really give you much information to help out here, not even the SHAs of the commits of both sides of the history. Fortunately, it's simple to figure out. If you run `git diff` you can get the SHAs of the commits recorded in both branches you were trying to merge.
To solve the problem, you need to figure out what state the submodule should be in. Strangely, Git doesn't really give you much information to help out here, not even the SHA-1s of the commits of both sides of the history. Fortunately, it's simple to figure out. If you run `git diff` you can get the SHA-1s of the commits recorded in both branches you were trying to merge.

[source,console]
----
Expand All @@ -554,9 +554,9 @@ index eb41d76,c771610..0000000

So, in this case, `eb41d76` is the commit in our submodule that *we* had and `c771610` is the commit that upstream had. If we go into our submodule directory, it should already be on `eb41d76` as the merge would not have touched it. If for whatever reason it's not, you can simply create and checkout a branch pointing to it.

What is important is the SHA of the commit from the other side. This is what you'll have to merge in and resolve. You can either just try the merge with the SHA directly, or you can create a branch for it and then try to merge that in. We would suggest the latter, even if only to make a nicer merge commit message.
What is important is the SHA-1 of the commit from the other side. This is what you'll have to merge in and resolve. You can either just try the merge with the SHA-1 directly, or you can create a branch for it and then try to merge that in. We would suggest the latter, even if only to make a nicer merge commit message.

So, we will go into our submodule directory, create a branch based on that second SHA from `git diff` and manually merge.
So, we will go into our submodule directory, create a branch based on that second SHA-1 from `git diff` and manually merge.

[source,console]
----
Expand Down Expand Up @@ -601,7 +601,7 @@ $ git commit -m "Merge Tom's Changes" <5>

<1> First we resolve the conflict
<2> Then we go back to the main project directory
<3> We can check the SHAs again
<3> We can check the SHA-1s again
<4> Resolve the conflicted submodule entry
<5> Commit our merge

Expand Down
6 changes: 3 additions & 3 deletions book/08-customizing-git/sections/attributes.asc
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,15 @@ Git attributes offers you two ways to do this.

First, you can inject the SHA-1 checksum of a blob into an `$Id$` field in the file automatically.
If you set this attribute on a file or set of files, then the next time you check out that branch, Git will replace that field with the SHA-1 of the blob.
It's important to notice that it isn't the SHA of the commit, but of the blob itself:
It's important to notice that it isn't the SHA-1 of the commit, but of the blob itself:

[source,console]
----
$ echo '*.txt ident' >> .gitattributes
$ echo '$Id$' > test.txt
----

The next time you check out this file, Git injects the SHA of the blob:
The next time you check out this file, Git injects the SHA-1 of the blob:

[source,console]
----
Expand All @@ -174,7 +174,7 @@ $Id: 42812b7653c7b88933f8a9d6cad0ca16714b9bb3 $
----

However, that result is of limited use.
If you've used keyword substitution in CVS or Subversion, you can include a datestamp – the SHA isn't all that helpful, because it's fairly random and you can't tell if one SHA is older or newer than another just by looking at them.
If you've used keyword substitution in CVS or Subversion, you can include a datestamp – the SHA-1 isn't all that helpful, because it's fairly random and you can't tell if one SHA-1 is older or newer than another just by looking at them.

It turns out that you can write your own filters for doing substitutions in files on commit/checkout.
These are called ``clean'' and ``smudge'' filters.
Expand Down
7 changes: 3 additions & 4 deletions book/08-customizing-git/sections/policy.asc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ You must look at each commit being pushed up, see if that string is in the commi

You can get a list of the SHA-1 values of all the commits that are being pushed by taking the `$newrev` and `$oldrev` values and passing them to a Git plumbing command called `git rev-list`.
This is basically the `git log` command, but by default it prints out only the SHA-1 values and no other information.
So, to get a list of all the commit SHAs introduced between one commit SHA and another, you can run something like this:
So, to get a list of all the commit SHA-1s introduced between one commit SHA-1 and another, you can run something like this:

[source,console]
----
Expand All @@ -58,7 +58,7 @@ dfa04c9ef3d5197182f13fb5b9b1fb7717d2222a
17716ec0f1ff5c77eff40b7fe912f9f6cfd0e475
----

You can take that output, loop through each of those commit SHAs, grab the message for it, and test that message against a regular expression that looks for a pattern.
You can take that output, loop through each of those commit SHA-1s, grab the message for it, and test that message against a regular expression that looks for a pattern.

You have to figure out how to get the commit message from each of these commits to test.
To get the raw commit data, you can use another plumbing command called `git cat-file`.
Expand Down Expand Up @@ -432,11 +432,10 @@ This script uses a syntax that wasn't covered in the Revision Selection section
[source,ruby]
----
`git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}`
.
----

The `SHA^@` syntax resolves to all the parents of that commit.
You're looking for any commit that is reachable from the last commit on the remote and that isn't reachable from any parent of any of the SHAs you're trying to push up – meaning it's a fast-forward.
You're looking for any commit that is reachable from the last commit on the remote and that isn't reachable from any parent of any of the SHA-1s you're trying to push up – meaning it's a fast-forward.

The main drawback to this approach is that it can be very slow and is often unnecessary – if you don't try to force the push with `-f`, the server will warn you and not accept the push.
However, it's an interesting exercise and can in theory help you avoid a rebase that you might later have to go back and fix.
2 changes: 1 addition & 1 deletion book/09-git-and-other-scms/sections/client-hg.asc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ $ tree .git/refs

Git-remote-hg is trying to make things more idiomatically Git-esque, but under the hood it's managing the conceptual mapping between two slightly different systems.
The `refs/hg` directory is where the actual remote refs are stored.
For example, the `refs/hg/origin/branches/default` is a Git ref file that contains the SHA starting with ``ac7955c'', which is the commit that `master` points to.
For example, the `refs/hg/origin/branches/default` is a Git ref file that contains the SHA-1 starting with ``ac7955c'', which is the commit that `master` points to.
So the `refs/hg` directory is kind of like a fake `refs/remotes/origin`, but it has the added distinction between bookmarks and branches.

The `notes/hg` file is the starting point for how git-remote-hg maps Git commit hashes to Mercurial changeset IDs.
Expand Down
Loading

0 comments on commit f782ee5

Please sign in to comment.