criscom
11/17/2014 - 10:49 PM

#tutorial: transcript from Git real on code school

#tutorial: transcript from Git real on code school

Git

Git History

Die Entstehung von GIT steht in direkter Verbindung mit der Entwicklung und Instandhaltung des Linux Kernels (1991 - 2002). In dieser Zeit wurden Änderungen in der Software als Patches und archivierte Dokumente unter den Entwicklern ausgetauscht. 2002 begann das Linux Kernel Projekt ein DVCS (Distributed Version Control System) namens BitKeeper zu verwenden.

Als BitKeeper 2005 begann, das Tool zu kommerziell zu vermarkten, 2005 stellte BitKeeper die open source Lizenz des Tools ein und vermarktete es ab sofort kommerziell. Aus diesem Anlass begann Linus Torvalds, Initiator und treibende Kraft bei der Entwicklung des Linux-Kernels, mit der Entwicklung eines eigenen Tools, in die er die Erfahrungen einfließen ließ, die man aus der Anwendung von BitKeeper gewonnen hatte.

Mit dem neuen System verfolgte man folgende Ziele:

  • Geschwindigkeit
  • Einfaches Design
  • Sehr gute Unterstützung von nicht linearer Entwicklung (Branches)
  • Vollständig verteilt
  • Ausgelegt, um große Projekte, wie den Linux Kernel, effektiv abwickeln zu können (Geschwindigkeit und Größe).

Seit 2005 hat sich GIT in ein DVCS entwickelt, das nicht nur leicht zu verwenden ist, sondern auch die oben beschriebenen Qualitäten in sich vereint: es ist sehr schnell, sehr effizient auch bei großen Projekten und zeichnet sich durch ein solides Branching-System für nicht-lineare Entwicklung aus. source: GitPro by Scott Chacon

Git Basics

Git unterscheidet sich signifikant von anderen VCS wie Subversion und Perforce. Daher ist es leichter, Git zu verstehen wenn man Subversion oder Perforce gar nicht kennt. Der wesentliche Unterschied liegt nicht im Interface - darin sind sie sich übrigens ziemlich ähnlich - sondern in der Art und Weise, wie Git Informationen speichert und darüber nachdenkt.

Snapshots und keine Diffs

Der wesentlichste Unterschied zwischen GIT und jedem anderen CVS liegt in der Art, wie GIT mit den Daten umgeht. Die meisten anderen VCS speichern Informationen als eine Liste von dokumentbasierenden Änderungen. Diese Systeme behandeln die in ihnen gespeicherte Information als ein Set von Dateien und der Änderungen für jede einzelne Datei im Projektverlauf.

GRAFIK

Git behandelt und speichert Daten völlig anders, nämlich als ein Set von Momentaufnahmen (Snapshots) eines kleinen Dateisystems. Jedes Mal wenn man einen Commit erstellt - oder den Zustand des Projekts in Git speichert - erstellt Git ein Bild vom Zustand aller Dokumente zu diesem Moment und speichert eine Referenz zu dieser Momentaufnahme. Daraus entstammt auch die Effizient von Git: ändert sich eine Datei nicht, dann speichert Git diese Datei nicht wieder ab, sondern Git speichert einfach einen Link zur bereits in Git vorhandenen Datei. Demnach behandelt Git die in ihm gespeicherten Daten wie einen Strom von Momentaufnahmen.

GRAFIK

Das ist der wesentlichste Unterschied zw Git und nahezu allen anderen VCS. Dieser Unterschied macht Git zu einem mini Dateisystem mit einigen zusätzlichen mächtigen Tools und daher zu weit mehr als einem einfachen VCS. Dieser Unterschied liegt auch der Möglichkeit zu Grunde, beliebig viele Branches eines Projektes parallel zu führen.

Fast jeder Befehl wir lokal ausgeführt

Ein Großteil der Git Befehle wird lokal ausgeführt. Daher werden in erster Linie nur lokale Dateien und Ressourcen benötigt. Dadurch fällt zB die in CVCS (Centralized Version Control Systems) immanente Network-Latenz vollkommen weg und macht Git unheimlich schnell. Da man den gesamten Verlauf des Projekts direkt auf seinem Rechner hat, laufen die meisten Operationen beinahe unmittelbar ab. Daher kann man auch an Projekten arbeiten, wenn man offline ist.

Git hat Integrität

Jede Änderung in Git erhält eine Checksumme bevor sie gespeichert wird. Diese Checksumme dient zur Referenzierung der Änderung. Das bedeutet, dass es nahezu unmöglich ist, etwas zu ändern, ohne dass Git davon erfährt. Diese Funktionalität ist auf der untersten Ebene in Git verbaut und ist fundamentaler Teil seiner Philosophie. Dadurch ist es nicht möglich, dass Information verloren geht oder eine Datei korrumpiert wird ohne dass Git darauf aufmerksam wird.

Der von Git verwendete Mechanismus für die Bildung der Checksumme wird SHA-1 hash genannt. Es handelt sich dabei um einen 40 Zeichen langen String, der sich aus hexadezimalen Zeichen (0-9 und a-f) zusammen setzt. Die Kalkulation der Checksumme basiert auf dem Inhalt einer Datei oder der Dateistruktur in Git.

Beispiel für einen SHA-1 hash: cb6e11ad9518e9c7f7974bdd760b5c4f41739670

Git verwendet diese hash Werte nahezu überall. Die Informationen in Git werden nicht mit dem Dateinamen gespeichert sonder mit dem hash Wert des Inhalts der Dateien.

Grundsätzlich fügt Git nur Daten hinzu

Git macht es einem nicht einfach, Daten zu verlieren, wie es grundsätzlich nur Daten dem System hinzufügt. Auch kann man fast alles wieder rückgängig machen. Natürlich kann man Daten verlieren oder Änderungen durcheinanderbringen aber sobald man etwas in einer Momentaufnahme über einen Commit festgehalten hat, wird es sehr sehr schwer diese Momentaufnahme wieder zu verlieren - speziell dann wenn man die Daten auf seinem lokalen System sichert oder die Git Datenbank auf ein anderes Repository pusht.

Dadurch eignet sich Git hervorragen für Experimente ohne Gefahr zu laufen, ein Projekt vollkommen an die Wand zu fahren. source: GitPro by Scott Chacon

The Three States => The Tree Trees of Git

Working Directory | Staging Area aka Index | Repository

Git can be understood as a content manager of three different trees. Tree can be seen as a "collection of files", not specifically the data structure - in a few cases the Index doesn't exaclty act like a tree, though.

Git as a system manages and manipulates three trees in its normal operation:

The Tree Roles
The HEADlast commit snapshot, next parent
The Indexproposed next commit snapshot
The Working Directorysandbox

The HEAD - last commit snapshot, next parent

The HEAD in Git is the pointer to the current branch reference, which, in turn, is a pointer to the last commit you made or the last commit that was checked out into your working directory. That also means it will be the parent of the next commit you do. It's generally simplest to think of it as HEAD is the snapshot of your last commit.

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

$ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
fdd1783da5bb002780fa710575664e3f76097fac

$ git cat-file -p fdd1783da5bb002780fa710575664e3f76097fac
tree e76e6dc41889d1dbce4b1274ac424bc4532fd3d6
parent 3aa961cc48b494309241ce85b42134afc8952e36
author criscom <criscom27@gmail.com> 1462872030 +0200
committer criscom <criscom27@gmail.com> 1462872030 +0200

Add git reset information table from Mark Dominus

$ git ls-tree -r e76e6dc41889d1dbce4b1274ac424bc4532fd3d6
100644 blob dc413f6a9dca0f7b2aac71eab7e279aa59c342c8    git-real.md

The Index - next proposed commit snapshot

The Index is your proposed next commit. It is not technically a tree structure, it's a flattened manifest. When you run git commit, that command only looks at your Index by default, not at anything in your working directory. So it's simplest to think of it as the Index is the snapshot of your next commit.

$ git ls-files -s
100644 dc413f6a9dca0f7b2aac71eab7e279aa59c342c8 0   git-real.md

The Working Directory - sandbox, scratch area

Finally, you have your working directory. This is where the content of files are placed into actual files on your filesystem so they're easily editable by you. The Working Directory is your scratch space, used to easily modify file content.

The Workflow

Git is all about recording snapshots of your project by manipulating these three trees, or collections of contents of files.

When checking out a branch, it changes HEAD to point to the new commit, populates the Index with the snapshot of that commit, then checks out the contents of the files in your Index into your Working Directory.

The Role of Reset

git reset directly manipulates these three trees in a simple and predictable way. It does up to three basic operations

Step 1: Moving HEAD - killing me --soft [ly]
git log -3 --pretty=oneline
2b8da2c17a316d53d2f14f7557bedbe03a40fd20 Add a line to 03.md
f8ba5a397d76dbf7231c1613d2394124dea2e2ed Add lib folder and readme file
fb3bfdfbca3bdfb946d95dc28802cf6ae441b73a Add newline to 01.md

Unlike checkout, git reset does not move what branch HEAD points to, it directly changes the SHA of the reference itself. This means if HEAD is pointing to the 'master' branch, running git reset f8ba5a3 will first of all make 'master' point to f8ba5a3 before it does anything else.

$ git reset f8ba5a3
Unstaged changes after reset:
M   03.md

$ git log -3 --pretty=oneline
f8ba5a397d76dbf7231c1613d2394124dea2e2ed Add lib folder and readme file
fb3bfdfbca3bdfb946d95dc28802cf6ae441b73a Add newline to 01.md
0a829f3f15015bcf9fe9b57d2e45acdf88115ae6 Add a third line to 01.md

$ git status
On branch 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:   03.md

no changes added to commit (use "git add" and/or "git commit -a")

No matter what form of resetwith a commit you invoke, this is the first thing it will always try to do. If you add the flag --soft, this is the only thing it will do. With --soft, reset will simply stop there.

git reset --soft HEAD~

What it does is essentially undoing the last commit that was made. It moves HEAD to the parent commit and move the commited file changes into the Index.

When you run git commit, Git will create a new commit and move the branch that HEAD points to up to it. When you resetback to HEAD~ (the parent of HEAD), you are moving the branch back to where it was without changing the Index (staging area) or Working Directory. You could now do a bit more work and commit again to accomplish baiscally what git commit --amend would have done.

If you run git status you'll see the difference between the Index and what the new HEAD is.

Step 2: Updating the index - having --mixed [feelings]

The next thing resetwill do is to update the Index with the contents of whatever tree HEAD now points to so they're the same.

git reset --mixed HEAD~
Unstaged changes after reset:
M   03.md

$ git log -3 --pretty=oneline
f8ba5a397d76dbf7231c1613d2394124dea2e2ed Add lib folder and readme file
fb3bfdfbca3bdfb946d95dc28802cf6ae441b73a Add newline to 01.md
0a829f3f15015bcf9fe9b57d2e45acdf88115ae6 Add a third line to 01.md

$ git status
On branch 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:   03.md

If you specify the --mixed option, reset will stop at this point. This is also the default, so if you specify no option at all, this is where the command will stop.

What git reset --mixed HEAD~ did was

- undo the last `commit`  
- but also _unstage_ everything  

We rolled back to before we ran all our git adds AND git commit.

Step 3: Updating the Working Directory - math is --hard

The third thing that resetwill do is to then make the Working Directory look like the Index. If you use the --hard option, it will continue to this stage.

With git reset --hard HEAD~ you

- undo the last commit
- all the git adds
- and all the work you did in your working directory.

Thus you will lose all the changes in the last commit. It's important to note at this point that this is the only way to make the resetcommand dangerous (ie: not working directory safe). Any other invocation of resetcan be pretty easily undone, the --hardoption cannot, since it overwrites (without checking) any files in the Working Directory.

$ git log -3 --pretty=oneline
3e2357ed723865d15654bedc2a1b2f2d6acea95d Before git reset --hard
f8ba5a397d76dbf7231c1613d2394124dea2e2ed Add lib folder and readme file
fb3bfdfbca3bdfb946d95dc28802cf6ae441b73a Add newline to 01.md

$ git reset --hard HEAD~
HEAD is now at f8ba5a3 Add lib folder and readme file

$ git log -3 --pretty=oneline
f8ba5a397d76dbf7231c1613d2394124dea2e2ed Add lib folder and readme file
fb3bfdfbca3bdfb946d95dc28802cf6ae441b73a Add newline to 01.md
0a829f3f15015bcf9fe9b57d2e45acdf88115ae6 Add a third line to 01.md

In this particular case, we still have the changes in 03.md in a commit in our Git DB that we could get back by looking at our reflog, but if we had not committed it, Git still would have overwritten the file.

Below was taken from: http://blog.plover.com/prog/git-reset.html
The Git subcommand git-reset is one of very few Git commands that can permanently destroy real work. git checkoutcan also destroy the working tree.

working directoyindex/staging areatargetworking directoryindexHEAD
ABC--softABC
--mixedACC
--hardCCC
--merge(disallowed)

git-reset does up to three things:

  1. It points the HEAD ref at a new 'target' commit, if you specified one.
  2. Then it copies the tree of the HEAD commit to the index, unless you said --soft.
  3. Finally, it copies the contents of the index to the working tree, if you said --hard.

Git Reset recap

The resetcommand overwrites these three trees in a specific order, stopping where you tell it to:

- #1 Move HEAD to a different commit (stop if --soft)
- #2 THEN make the Index look like that (stop here unless --hard)
- #3 THEN make the Working Directory look like that

There are also --merge and --keep options.

Git Reset with a path ==> unstaging a staged file

By specifying a path we can use git reset filename.txt to update part of the Index or the Working Directory with previsously committed content.

Running git reset file.txt assumes git reset --mixed HEAD filen.txtwhich will:

- ~~#1 Move HEAD to a different commit (stop if --soft)~~
- #2 THEN make the Index look like that (~~stop here unless --hard~~)

So it essentially just takes whatever file.txtlooks like in HEAD and puts that in the Index. Basicall git reset file.txt is the opposite of git add file.txt.

By specifying a specific commit, we could pull a specific file version to populate our Index, like git reset 0a829f3 03.md

Git reflog

git reflog shows an ordered list of the commits that HEAD has pointed to: it's undo history for your repo. The reflog isn't part of the repo itself (it's stored separately to the commits themselves) and isn't included in pushes, fetches or clones; it's purely local.

Aside: understanding the reflog means you can't really lose data from your repo once it's been committed. If you accidentally reset to an older commit, or rebase wrongly, or any other operation that visually "removes" commits, you can use the reflog to see where you were before and git reset --hard back to that ref to restore your previous state. Remember, refs imply not just the commit but the entire history behind it.

$ git reflog
f8ba5a3 HEAD@{0}: reset: moving to HEAD~
3e2357e HEAD@{1}: commit: Before git reset --hard
f8ba5a3 HEAD@{2}: reset: moving to HEAD~
7ce43b9 HEAD@{3}: commit: Committing file 03.md again
f8ba5a3 HEAD@{4}: reset: moving to HEAD~
4490b4d HEAD@{5}: commit: Recommit file changes in 03.md
f8ba5a3 HEAD@{6}: reset: moving to f8ba5a3
2b8da2c HEAD@{7}: commit: Add a line to 03.md
...

$ git checkout 3e2357e

Undoing things from gitreal

Unstaging files

git reset HEAD <file>
git reset HEAD styles.css

Moves the file from the Staging Area to the Working Directory. The file's modifications remain.

Discard changes since last commit

git checkout -- <file>
git checkout -- styles.css

Removes the changes added in the file completely. git checkout -- <file> is only possible in the Working Directory.

Difference between reset and checkout

In their simplest form, reset resets the index without touching the working tree, while checkout changes the working tree without touching the index.

  • git reset is specifically about updating the index, moving the HEAD.
  • git checkout is about updating the working tree (to the index or the specified tree). It will update the HEAD only if you checkout a branch (if not, you'll end up with a detached HEAD)

See for more details the discussion on stackoverflow

Skip staging and commit

git commit -a -m "Modify readme"

not adding files we are tracking

Undoing a commit

git reset --soft HEAD^

  • Reset into staging
  • Undo last commit, put changes into staging
  • Move to commit before 'HEAD'
  • Now we can make changes and re-commit

Undo last commit and all changes

git reset --hard HEAD^

Undo last 2 commits and all changes

git reset --hard HEAD^^

Removing files

In order to remove files from your tree, you can simply run:

git rm <filename>

This will remove that file from the index (and thus from the next commit) as well as from your working diretory. On your next commit, the tree that commit points to will simply not contain that file anymore. The file will be removed from the folder.

Adding to a commit

git add todo.txt
git commit --amend -m "Modify readme & add todo.txt."
  • When we forgot to add a file
  • Add to the last commit
  • Whatever has been staged is added to last commit

Git diff - show differences

Show unstaged differences since last commit

git diff

As a matter of fact running git diff with no arguments, will show the differences between the current working directory and the index, i.e. the last time git add was ran. What you see is simply a patch file.

Viewing staged differences

git diff --staged

does the same as running git diffwith no arguments but in contrast to above command, it will show differences of staged files and the working directory/git directory, i.e. the last time git commit was ran.

Show differences between two commits

git diff --numstat commit-sha1 commit-sha1

git diff --numstat 2d3f5d03e76d2c1846af0a76e2e84b74cf8a1065 cdcd6bee6c8bf5b330c2eb22359c04417472a5ee
0       5       01.md
0       1       02.md

git diff --stat older-commit-sha1 newer-commit-sha1

git diff --stat cdcd6bee6c8bf5b330c2eb22359c04417472a5ee
01.md | 5 +++++
02.md | 1 +
2 files changed, 6 insertions(+)

See specific differences

git diff older-commit-sha1 newer-commit-sha1 -- filename

git diff cdcd6bee6c8bf5b330c2eb22359c04417472a5ee 2d3f5d03e76d2c1846af0a76e2e84b74cf8a1065 -- 01.md
diff --git a/01.md b/01.md
index e69de29..8b6d5f6 100644
--- a/01.md
+++ b/01.md
@@ -0,0 +1,5 @@
+add 1st line
+add 2nd line
+add 3rd line - stop
+abc
+def

Generating patch files

The default output of the git diff command is a valid patch file. You can pipe the output into a file and email it to someone, so that they can apply it with the patch command.

Creating a patch from a branch

If you have done some work in an 'experiment' branch, you could create a patch file like this:

git diff master..experiment > experiment.patch

Applying a patch

patch -p < ~/experiment.patch

Interactive adding

Interactive adding makes for a more controlled and thematic set of commits and is a very powerful tool to controlling what goes into each commit.

Say we add changes to our 01.md and 02.md file and add a new TODO file to our project. Later we come back and want to commit, but we don't remember which files hat to do with each other and we don't just want to commit them all together because that's confusing for collaborators trying to review our code.

Interactive mode lets us modify our index interactively before committing.

git add -i
         staged      unstaged path
1:    unchanged        +2/-1 01.md
2:    unchanged        +3/-1 02.md

*** Commands ***
  1: status   2: update   3: revert   4: add untracked
  5: patch    6: diff     7: quit     8: help
What now> 

We can see that we have two files that are being tracked (have been added at some point in the past) that have been modified. We cannot yet see our new TODO file, though. To add that, type 4 for the add untracked option and hit Enter.

What now> 4
1: TODO
Add untracked>> 
added one path

You will see all the untracked files in your working directory. Type the numbers of the files you want to add or a range (i.e.: 1-5), and hit enter twice and your're done. This will drop you back to the main menu. You can then type 1 to see what your index looks like now.

What now> 1
         staged      unstaged path
1:    unchanged        +2/-1 01.md
2:    unchanged        +3/-1 02.md
3:        +0/-0       nothing TODO

You can see that the TODO file is now staged (in the index), but the other two are not.

Let's add 01.md, but not the 02.md file and commit it. To do that, we hit 2, which lists the files we can update, type 1and enter to add the 01.md file, then hit enter again to go back to the main menu. Then we hit 7to exit an drun the git commitcommand.

What now> 2
       staged     unstaged path
  1:    unchanged        +2/-1 01.md
  2:    unchanged        +3/-1 02.md
Update>> 1
       staged     unstaged path
* 1:    unchanged        +2/-1 01.md
  2:    unchanged        +3/-1 02.md
Update>> 
updated one path
What now> 7
Bye.
git commit -m "01.md and TODO file added"
[master 049da5b] 01.md and TODO file added
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 TODO

You can also do more complicated things, like going through all of your change patches hunk by hunk, deciding if each hunk should be applied to the next commit or not. This means that if you’ve made a bunch of changes to one le, you can commit part of those changes in one commit, and the rest in a second. Try the patch menu option in the Interactive Adding menu to try this out.

Beware of using interactive adding if you are already used to running git commit -a. If you run through the whole interactive add process and then run git commit -a, it will basically ignore everything you just did and just add all modified files.

Formatting Log output

--pretty is a useful option for formatting the ouput in different ways.

For example, we can list the commit SHA-1s and the first line of the message with --pretty=online:

git log --pretty=oneline
534860566b7bae4017d18cadf391371592f5c55f Remove experiment.patch
2ee75e651b9e64811297612ba2caa92f7f347ebf Add fourth line to 01.md
5a6611996b06ce9bd2264cbed29f3922eaef6ca3 Add fourth line to 01.md
d2349d29ae0db360893c27c62181a5283c100cef Add 2 lines to 01.md
cdcd6bee6c8bf5b330c2eb22359c04417472a5ee Add 01.md

With --pretty, you can choose between oneline, short, medium, full, fuller, email, raw and format:(string), where (string) is a format you specify with variables (ex: --pretty=format:”%an added %h on %ar” will give you a bunch of lines like “criscom added 5348605 on 21 minutes ago”).

git log --pretty=format:"%an added %h on %ar"
criscom added 5348605 on 21 minutes ago
criscom added e69dab6 on 26 minutes ago
criscom added cdcd6be on 4 hours ago

Filtering Log Output

There are also a number of options for ltering the log output. You can specify the maximum number of commits you want to see with -n, you can limit the range of dates you want to see commits for with —since and —until, you can lter it on the author or committer, text in the commit message and more. Here is an example showing at most 30 commits between yesterday and a month ago by me : git log -n 30 --since=”1 month ago” --until=yesterday --author=”criscom”

Common options to git log

OptionDescription
-pShow the patch introduced with each commit.
--statShow statistics for files modified in each commit.
--shortstatDisplay only the changed/insertions/deletions line from the --stat command.
--name-onlyShow the list of files modified after the commit information.
--name-statusShow the list of files affected with added/modified/deleted information as well.
--abbrev-commitShow only the first few characters of the SHA-1 checksum instead of all 40.
--relative-dateDisplay the date in a relative format (for example, “2 weeks ago”) instead of using the full date format.
--graphDisplay an ASCII graph of the branch and merge history beside the log output.
--prettyShow commits in an alternate format. Options include oneline, short, full, fuller, and format (where you specify your own format).

Showing Objects

git show

Running this command on a file will simply output the contents of the file.

Showing commits

If you call it on a commit object (~ a tree), you will get simple imformation about the commit (the author, message, date, etc) and a diff of what changed between taht commit and its parents.

git show master
commit fb3bfdfbca3bdfb946d95dc28802cf6ae441b73a
Author: criscom <criscom27@gmail.com>
Date:   Tue May 10 10:06:31 2016 +0200

Add newline to 01.md

diff --git a/01.md b/01.md
index 207ee39..8c17d9d 100644
--- a/01.md
+++ b/01.md
@@ -7,4 +7,4 @@ ghijk
 we add a new line
 and a second line

-and now a third
\ No newline at end of file
+and now a third

git show master^

will show the changes between the penultimate (second to last) commit and its parent.

Showing Trees

git ls-tree

shows tress and displays SHA-1s of all the blobs and trees that it points to.

git ls-tree master
100644 blob 8c17d9dec9efc6d0ad05372d7f6869d833181d0f    01.md
100644 blob fd547b8f094e7cd3bbdff1225f861be9e81a1aa8    02.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    03.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    TODO
040000 tree b405b70664efcdc5de910eba03e55f14745a9c6f    lib

Christophs-iMac:gittest criscom$ git ls-tree master^
100644 blob 8c17d9dec9efc6d0ad05372d7f6869d833181d0f    01.md
100644 blob fd547b8f094e7cd3bbdff1225f861be9e81a1aa8    02.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    03.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    TODO

Christophs-iMac:gittest criscom$ git ls-tree master{tree}
fatal: Not a valid object name master{tree}


Christophs-iMac:gittest criscom$ git ls-tree master^{tree}
100644 blob 8c17d9dec9efc6d0ad05372d7f6869d833181d0f    01.md
100644 blob fd547b8f094e7cd3bbdff1225f861be9e81a1aa8    02.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    03.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    TODO
040000 tree b405b70664efcdc5de910eba03e55f14745a9c6f    lib


Christophs-iMac:gittest criscom$ git ls-tree master^^{tree}
100644 blob 8c17d9dec9efc6d0ad05372d7f6869d833181d0f    01.md
100644 blob fd547b8f094e7cd3bbdff1225f861be9e81a1aa8    02.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    03.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    TODO

You can also run the command recursively, so you can see all the subtrees as well. This is a great way to get the SHA-1 of any blob anywhere in the tree without having to walk it one node at a time.

git ls-tree -r -t  master^{tree}
100644 blob 8c17d9dec9efc6d0ad05372d7f6869d833181d0f    01.md
100644 blob fd547b8f094e7cd3bbdff1225f861be9e81a1aa8    02.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    03.md
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391    TODO
040000 tree b405b70664efcdc5de910eba03e55f14745a9c6f    lib
100644 blob 06f196f556db9fc496ab9c12f7a047e4157add4e    lib/readme.txt

git ls-tree master^{tree} => git ls-tree master

Showing Blobs

Lastly, you may want to extract the contents of individual blobs. The cat-file command is an easy way to do that, and can also serve to let you know what type of object a SHA-1 is, if you don’t know. It is sort of a catch-all command that you can use to inspect objects.

git cat-file -t/-p SHA-1

git cat-file -t 8c17d9dec9efc6d0ad05372d7f6869d833181d0f
blob

git cat-file -p 8c17d9dec9efc6d0ad05372d7f6869d833181d0f
add 1st line
add 2nd line
add 3rd line - stop
abc
def
ghijk
we add a new line
and a second line

and now a third

Showing differences between

Working directory and staging area

git diff

Staging area and latest commit

git diff --staged

Working directory and commit 4ac0a6733

git diff 4ac0a6733

Commit 4ac0a6733 and the latest commit

git diff 4ac0a6733 HEAD

Commit 4ac0a6733 and commit 826793951

git diff 4ac0a6733 826793951

Show differences in log

git log -p

See git diff documentation

Working with remote repos

Adding a remote

git remote add origin https://github.com/criscom/repository-name.git

Which remotes does git repository know about

git remote -v

Pushing to remote

git push -u origin master

origin: remote repository name
master: local branch to push

Pulling from remote

git pull

Having multiple remote

To add new remotes: git remote add <name> <address>

To remove remotes: git remote rm <name>

To push to remotes: git push -u <name> <branch>

is usuall "master"

Don't do these after you push

git reset --soft HEAD^
git commit --amend -m "New Message"
git reset --hard HEAD^
git reset --hard HEAD^^

CLONING & BRANCHING

git clone https://github.com/codeschool/git-real.git git-demo

git-demo = local folder name

  • Downloads the entire repository into a new git-demo directory
  • Adds the 'origin' remote, pointing it to the clone URL
  • Checks out initial branch (likely master) and sets the head.

Branching out

Need to work on a feature that will take some time? Time to branch out.

git branch nameofbranch
git checkout nameofbranch

Merge

git checkout master
git merge nameofbranch

Branch clean up

After merging

git branch -d nameofbranch

Create branch and automatically checking it out

git checkout -b admin

==> Automatically switches to branch admin

REMOTE BRANCHES AND TAGS

git checkout -b shopping_cart

create branch shopping_cart

git push origin shopping_cart

links local branch to the remote branch

git branch -r

list all remote branches

git checkout shopping_cart

Branch shopping_cart set up to track remote branch shopping_cart from origin. Switched to a new branch 'shopping_cart'

git remote show origin

Shows all remote and local branches and how they are connected

git push origin :shopping_cart

Delete a remote branch

git remote prune origin

to clean up deleted remote branches

git push heroku-stagin staging:master

Will push and deploy staging on heroku

Tagging

A tag is a reference to a commit (used mostly for release versioning)

git tag

list all tags

git checkout v0.0.1

checkout code at commit

git tag -a v0.0.3 -m "version 0.0.3"

to add a new tag

git push --tags

to push new tags

Bibliography:

http://schacon.github.io/2008/04/29/peepcode-git-book.html
http://scottchacon.com/2011/07/11/reset.html
http://blog.plover.com/prog/git-reset.html