#LyX 1.6.4 created this file. For more info see http://www.lyx.org/ \lyxformat 345 \begin_document \begin_header \textclass article \use_default_options true \language english \inputencoding auto \font_roman default \font_sans default \font_typewriter default \font_default_family default \font_sc false \font_osf false \font_sf_scale 100 \font_tt_scale 100 \graphics default \paperfontsize default \use_hyperref false \papersize default \use_geometry false \use_amsmath 1 \use_esint 1 \cite_engine basic \use_bibtopic false \paperorientation portrait \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \defskip medskip \quotes_language english \papercolumns 1 \papersides 1 \paperpagestyle default \tracking_changes false \output_changes false \author "" \author "" \end_header \begin_body \begin_layout Title Git repository internals \end_layout \begin_layout Part What's inside \end_layout \begin_layout Standard Git repository consists of the following objects: \end_layout \begin_layout Itemize Object database \end_layout \begin_deeper \begin_layout Itemize Blobs \end_layout \begin_layout Itemize Trees \end_layout \begin_layout Itemize Commits \end_layout \begin_layout Itemize Annotated tags \end_layout \end_deeper \begin_layout Itemize Refs \end_layout \begin_deeper \begin_layout Itemize Your branches and tags \end_layout \begin_layout Itemize Remote branches \end_layout \begin_layout Itemize Special (HEAD etc.) \end_layout \end_deeper \begin_layout Itemize Config/misc \end_layout \begin_deeper \begin_layout Itemize .git/config \end_layout \begin_layout Itemize hooks \end_layout \begin_layout Itemize reflogs \end_layout \end_deeper \begin_layout Standard . \end_layout \begin_layout Standard Blob is a piece of content without metadata \end_layout \begin_layout Standard Tree is a list of file/directory names pointing at blobs or other trees \size tiny /* not considering subprojects */ \size default . \end_layout \begin_layout Standard Commit is an object that 1. has pointer to other commit[s], 2. has pointer to tree (project root), 3. contains metadata (commit message, dates, authors, etc.) \end_layout \begin_layout Standard Each ref points to (usually last) commit in some branch (either your or remote) \end_layout \begin_layout Part A short story \end_layout \begin_layout Section Adding files \end_layout \begin_layout Standard Let's create a simple project: \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout mkdir qqq && cd qqq \end_layout \begin_layout Plain Layout mkdir src \end_layout \begin_layout Plain Layout echo 'int main(){printf("Helo wrold \backslash r");}' > src/main.c \end_layout \begin_layout Plain Layout cat > Makefile << \backslash EOF \end_layout \begin_layout Plain Layout all: \end_layout \begin_layout Plain Layout gcc src/*.c -o hello \end_layout \begin_layout Plain Layout EOF \end_layout \begin_layout Plain Layout \end_layout \begin_layout Plain Layout git init \end_layout \begin_layout Plain Layout git add . \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Quotes eld \end_inset git add . \begin_inset Quotes erd \end_inset addded src/main.c and Makefile. It created two blobs (main.c and Makefile) and two trees (root tree and \begin_inset Quotes eld \end_inset src \begin_inset Quotes erd \end_inset tree). \end_layout \begin_layout Standard \begin_inset Graphics filename git1.svg scale 50 \end_inset \end_layout \begin_layout Section Committing \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout git commit -m "Add files to project" \end_layout \end_inset Now we have just created a commit. Commit is pointed by ref (name of branch), tree is pointed by commit, blob is pointed by tree. \end_layout \begin_layout Standard \begin_inset Graphics filename git2.svg scale 50 \end_inset \end_layout \begin_layout Section More commits \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout echo 'int main(){ printf("%s", "Hello world \backslash n"); return 0;}' > src/main.c \end_layout \begin_layout Plain Layout git commit -am "Typo fix" \end_layout \end_inset \end_layout \begin_layout Standard We changed main.c. It gets new blob. So we need to have new \begin_inset Quotes eld \end_inset src \begin_inset Quotes erd \end_inset tree (with updated blob pointer). So we need to have the new root tree (with updated \begin_inset Quotes eld \end_inset src \begin_inset Quotes erd \end_inset tree pointer). New commit points to the new tree. \end_layout \begin_layout Standard \begin_inset Graphics filename git3.svg scale 50 \end_inset \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout mkdir src/plugins \end_layout \begin_layout Plain Layout echo 'void func(){}' > src/plugins/extra.c \end_layout \begin_layout Plain Layout git add src/plugins \end_layout \begin_layout Plain Layout git commit -m "Add a plugin" \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Graphics filename git4.svg scale 50 \end_inset \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout cat > Makefile << \backslash EOF \end_layout \begin_layout Plain Layout all: \end_layout \begin_layout Plain Layout gcc src/*.c src/plugins/*.c -o hello \end_layout \begin_layout Plain Layout EOF \end_layout \begin_layout Plain Layout git add Makefile \end_layout \begin_layout Plain Layout git commit -m "Oh, forgot about Makefile" \end_layout \end_inset \end_layout \begin_layout Standard \begin_inset Graphics filename git5.svg scale 50 \end_inset \end_layout \begin_layout Standard Note that now \begin_inset Quotes eld \end_inset src \begin_inset Quotes erd \end_inset tree is reused from previous commit (as nothing have changed there) \end_layout \begin_layout Part Rewriting history \end_layout \begin_layout Standard Commit \begin_inset Quotes eld \end_inset c54c \begin_inset Quotes erd \end_inset is not useful: the very next commit fixes obvious thing. We want to merge that two commits into one, eliminating the \begin_inset Quotes eld \end_inset wrong \begin_inset Quotes erd \end_inset intermediate c54c. \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout git rebase -i HEAD~2 # ~2 means we need to process 2 last commits \end_layout \begin_layout Plain Layout # in editor: \end_layout \begin_layout Plain Layout pick c54c \end_layout \begin_layout Plain Layout squash ff5f \end_layout \end_inset \end_layout \begin_layout Standard This is convert commits c54c and ff5f to patches, rewind to commit 58cd then apply that two patches, but producing only one commit (you can also split and edit them). \size tiny /* Note: this case can be done simpler: \family typewriter git reset --soft HEAD~2 && git commit -m \begin_inset Quotes eld \end_inset Add a plugin \begin_inset Quotes erd \end_inset \family default */ \end_layout \begin_layout Standard Stale commits \begin_inset Quotes eld \end_inset ff5f \begin_inset Quotes erd \end_inset and \begin_inset Quotes eld \end_inset c54c \begin_inset Quotes erd \end_inset still remain in repository and can be used for recovery (unless finally cleaned by \begin_inset Quotes eld \end_inset git gc \begin_inset Quotes erd \end_inset ) \end_layout \begin_layout Standard \begin_inset Graphics filename git6.svg scale 50 \end_inset \end_layout \begin_layout Standard If/when stale commits get cleaned (they will be there for a certain time), it will be like this: \end_layout \begin_layout Standard \begin_inset Graphics filename git7.svg scale 50 \end_inset \end_layout \begin_layout Standard \begin_inset Quotes eld \end_inset ff5f \begin_inset Quotes erd \end_inset and \begin_inset Quotes eld \end_inset c54c \begin_inset Quotes erd \end_inset are gone, tree \begin_inset Quotes eld \end_inset aa54 \begin_inset Quotes erd \end_inset is gone too (as it is not referenced by anything anymore). \end_layout \begin_layout Part Interaction with other repositories \end_layout \begin_layout Standard We can fetch or push commits to other repositories. Obtaining (or publishing) a commit implies transferring it's trees and blobs as well. For example, \end_layout \begin_layout Standard \begin_inset listings inline false status open \begin_layout Plain Layout git remote add origin git://github.com/hello/exaple.git \end_layout \begin_layout Plain Layout git fetch origin +refs/heads/master:refs/remotes/origin/master \end_layout \end_inset \end_layout \begin_layout Standard Registers URL of remote repository under the name \begin_inset Quotes eld \end_inset origin \begin_inset Quotes erd \end_inset and then fetches origin's ref named \begin_inset Quotes eld \end_inset refs/heads/master \begin_inset Quotes erd \end_inset (or just \begin_inset Quotes eld \end_inset master \begin_inset Quotes erd \end_inset ) to our local ref \begin_inset Quotes eld \end_inset refs/remotes/origin/master \begin_inset Quotes erd \end_inset , replacing old \begin_inset Quotes eld \end_inset refs/remotes/origin/master \begin_inset Quotes erd \end_inset even if it is not direct child \size footnotesize (this will occur if, for example, somebody have fetched our commit ff5f or c54c and now we rewritten it to new one 7747) \size default . \end_layout \begin_layout Standard Note: This was a full form of fetch command, usually \begin_inset Quotes eld \end_inset git fetch origin \begin_inset Quotes erd \end_inset or \begin_inset Quotes eld \end_inset git fetch \begin_inset Quotes erd \end_inset does the required thing. \end_layout \begin_layout Standard Pushing command example is \begin_inset Quotes eld \end_inset git push origin 4112:refs/heads/master \begin_inset Quotes erd \end_inset . It also can have forcing \begin_inset Quotes eld \end_inset + \begin_inset Quotes erd \end_inset , source ref can be \begin_inset Quotes eld \end_inset master \begin_inset Quotes erd \end_inset or \begin_inset Quotes eld \end_inset HEAD \begin_inset Quotes erd \end_inset \size footnotesize (or even nothing - means \begin_inset Quotes eld \end_inset delete it \begin_inset Quotes erd \end_inset ) \size default instead of direct commit number \begin_inset Quotes eld \end_inset 4112 \begin_inset Quotes erd \end_inset or be configured for just \begin_inset Quotes eld \end_inset git push \begin_inset Quotes erd \end_inset to do what you expect. \end_layout \end_body \end_document