Learning GIT CodicePlastico.com
Why source control? Working fearless Experimenting Collaborating Version tracking :-) Blame someone :-) Zip files Deployment
What’s inside? All you need to run your project: Source code Build scripts Database scripts Tests Assets
What’s outside? External libraries Generated stuff: binaries, compiled CSSs, minified/bundled JSs, generated documentation, … IDE configuration settings (.vs, .idea, .settings, .project, …) …
Agenda Introduction to Git Obtaining and installing Git Basic Git operations Configuration Working with local repository Branches and Merges Remote repositories
Agenda Submodules Daily use Helpful commands
Git Built by Linus Torvalds and Linux community as an alternative to BitKeeper Developed starting from 3 april 2005 Release 1.0 on 21 december 2005 What it is, philosophy, history
Goals Facilitate Distributed Development Scale to handle thousands of developers Perform quickly and efficiently Maintain integrity and trust Enforce accountability. (who did what and why) Immutability What it is, philosophy, history
Goals Atomic transactions Support and encourage branched development Complete repositories Clean internal design Be free
Obtaining & installing Git http://git-scm.com/
What you get?
Quick intro… Demo di creazione di un nuovo repo e di aggiunta di un nuovo file
how svn works
how git works
Basic Git concepts Repositories Blobs Trees Commits Tags Index Workspace, index, trees, blob
Repositories Is the database of your project It provides a complete working copy of all the files in the repository and the copy of the repository itself It maintains two primarily data structures: object store and index. Everything is inside the .git folder
Blobs It contains the data of the files Each version of a file is represented as a blob It does not contains any metadata
Trees It contains one level of directory information It records blob identifiers, path names It can contains other trees
Commits Contains metadata of each change introduced into the repository Each commit points to a tree object and captures in one complete snapshot the state of the repository at the time the commit was performed
Commits A commit contains: The name of a tree object that actually identifies the associated files The name of committer and the time The commit message author and committer are usually the same
Tags Assign a readable name to a commit
Index Captures a version of the project’s overall structure at some moment in time It’s a layer between the working directory and the repository that tracks the files It doesn’t contains any file content
Content-addressable Names Git tracks content Each object has unique name produced applying SHA1 to the content The object store is based on the hashed computation of the contents of its objects If two separate file have the same content git store a single copy of them Git store every version of every file (not their difference) Two identical file have the same SHA1 whatever the names of the files are.
Object Store commit 09a0473 master tree blob1 blob2
A commit later… commit 09a0473 commit 11cf9410 master tree tree blob1
Inside the .git dir total 40 -rw-r--r-- 1 ema staff 22B May 17 13:37 COMMIT_EDITMSG -rw-r--r-- 1 ema staff 23B May 17 13:35 HEAD drwxr-xr-x 2 ema staff 68B May 17 13:35 branches -rw-r--r-- 1 ema staff 137B May 17 13:35 config -rw-r--r-- 1 ema staff 73B May 17 13:35 description drwxr-xr-x 11 ema staff 374B May 17 13:35 hooks -rw-r--r-- 1 ema staff 104B May 17 13:37 index drwxr-xr-x 3 ema staff 102B May 17 13:35 info drwxr-xr-x 4 ema staff 136B May 17 13:37 logs drwxr-xr-x 7 ema staff 238B May 17 13:37 objects drwxr-xr-x 4 ema staff 136B May 17 13:35 refs
File classification Tracked: already in the repository or staged in the index. Ignored: a file that git ignore because it is in the .gitignore list Untracked: a file that is not in the other two categories.
Demo… Change file status by creating it, adding it to the stage…. git add, rm, mv
git add Add the file contents to the index git add filename
git rm Remove files from the working tree and from the index git rm filename
git mv Move or rename a file, a directory, or a symlink git mv filename
git commit –m ”a message” Record changes to the repository git commit –m ”a message”
basic operations
.gitignore
Inside a commit A git commit is used to record changes to a repository git commit -m “refactoring” Git creates new blobs for any file that has changed and new trees for any directory that has changed reuse any blob or tree that has not changed pag 44
Inside a commit Every commit is atomic Every commit has a name 4eff6f95a00dbadb469e751b3b9bceb0b40159d5 HEAD is the last commit / the “tip” (of the current branch…)
Relative commit name Git uses relative name for commits: HEAD~1 HEAD~2 HEAD~N
Viewing the history Git log shows the commit history (by default, on the current branch) git log git log –-oneline git log –-graph –-all –decorate \ --oneline …
Git log Some useful options: --pretty: different format --graph: show the branch graph git log --pretty=format:'%C(yellow)%h %Cred%ad %Cblue%an %Cgreen%d %Creset%s' --date=short -- graph pretty: oneline, short, medium, full, fuller, email, raw
Git blame Who did it? git blame filename git blame filename
Branches A branch can represent an individual customer release A branch can encapsulate a development phase A branch can isolate the development of a single feature A branch can represent the work of an individual contributor
master branch Every git repository has (usually) the master branch It’s not special and can be deleted (if needed) it’s the trunk
Using branches There is at most one current branch HEAD represent the most recent commit (‘tip’) on the current branch
git branch name [starting_commit] Creating branches git branch name [starting_commit] It just introduce the name of the commit in the repo
Checking out branches git checkout name
Creating and checking out git checkout –b name [starting_commit]
Checking out branches Files and directories present in the branch being checked out but not in the current branch are checked out of the object store and placed into your working tree. Files and directories present in the current branch but absent in the branch being checked out will be removed from the working tree Files common to both branches are modified to reflect the content present in the checked out branch
Uncommitted changes Files and directories in the working directory that are not being tracked are left alone If there are local modification to a file that are different from changes that are present on the new branch, git issue an error message -f force the checkout discarding changes -m merge the changes to the new branch
Deleting branches git branch -d name
Deleting branches The current branch cannot be deleted Git won’t allow you to delete a branch that contains commits that are not also present on the current branch (use -D instead of -d to force it)
Tagging A tag is meant to be a static name that does not change over time Useful to mark versions: git tag -a v1.2 -m 'version 1.2'
tag git tag: list the tags git tag -l ‘v1.*’ : list the tags that matches the pattern
Diffs git diff: shows the difference between your working directory and the index git diff commit_id: summarizes the differences between the working directory and the given commit git diff --cached commit_id: show the differences between the staged changes in the index and the given commit git diff c1 c2: displays the differences between the two given commits git diff master feature1: shows the difference between the two specified branches
Diffs
Merges A merge unify two or more commit history branches (one commit can have multiple parents…)
git merge other_branch Merges git merge other_branch Working directory should be clean Conflicts can occur
Conflicts Git keeps track of problematic files by marking each one in the index as conflicted or unmerged
Conflicts
How git tracks conflicts ./git/MERGE_HEAD contains the SHA of the commit that is merging ./git/MERGE_MSG contains the default merge message used when commit to resolve the conflict The index contains 3 copies of each conflicted file: the merge base, “our” and “their” The conflicted version is not stored in the index
Resolve a conflict Adjust the file to mach the desired status git add file git commit –m "Resolved conflict"
git reset --hard [previuous_commit_id] Aborting a merge When in troubles git merge --abort If the commit is already done git reset --hard [previuous_commit_id] git saves the original branch HEAD in the ORIG_HEAD ref
Resolve a conflict Merge using other branch changes git merge --strategy-option theirs branch_name Merge using current changes git merge --strategy-option ours branch_name -X is the same of --strategy-option
Degenerate merges Already up to date: when all the commits from the other branch are already present in the target branch Fast-forward: when the current branch is already present in the other branch (other branch’s last commit is descendant of HEAD)
git merge —-squash other_branch Squash merges Sometimes is useful to squash all commits into a single commit git merge —-squash other_branch
Altering history A general rule: Feel free to alter and improve your repository commit history as long as no other developer has obtained a copy of your repository (more on this later…)
git reset --soft [commit_id] The --soft changes the HEAD ref to point to the given commit. The contents of index and working directory are left unchanged git reset --soft [commit_id]
git reset --mixed [commit_id] The --mixed changes the HEAD ref to point to the given commit. The index content is modified to align with the tree structure of the given commit, but the working directory remains unchanged This is the default option for reset
git reset --hard [commit_id] The --hard changes the HEAD ref to point to the given commit. The index content and the working directory are modified to align with the tree structure of the given commit.
git reset In practice: reset moves the current branch HEAD within the commit graph to a specific commit. If --hard is specified the working directory is transformed as well.
git reset Option HEAD Index Working directory --soft Y N --mixed --hard
git cherry-pick commit Applies the changes introduced by a commit on the current branch It will introduce a new commit adding it to the history git cherry-pick commit
git revert It applies the inverse of the given commit git revert commit
amend Sometimes happens to forgot a file or to correct a typo It doesn’t create a new commit but change the last one (altering history!!!) git commit --amend
rebase The normal merge command “soil” the current branch rebase is a sort of cleaner merge forward-port local commits to the updated upstream head
rebase master topic git checkout topic git rebase master A B C D E W X Y Z topic git checkout topic git rebase master
rebase A B C D E master W’ X’ Y’ Z’ topic
git add something something_else git rebase --continue If conflict is found the rebase operation suspend its process temporarily so that the conflict can be resolved continue with git add something something_else git rebase --continue
rebase (interactively) Can be used to squash or modify commits git rebase -i master~3
rebase -i
The Stash git stash [save] Is a mechanism for capturing your work in progress allowing to save it and return to it later Save and clear any modification Save the snapshot in a stack git stash [save] Something like a commit… without a commit! :-)
git stash branch new_branch The Stash git stash pop Extract and remove the snapshot from the stash and apply it to the current branch git stash apply Apply the snapshot to the current branch without removing it from the stash git stash branch new_branch Apply the snapshot creating a new branch Apply the snapshot to the current branch without removing it from the stash
git stash drop [snapshot_id] The Stash git stash list List available snapshots git stash drop [snapshot_id] Remove given (default: last) snapshot Apply the snapshot to the current branch without removing it from the stash
remote repositories By now everything was local Git is a DVCS (D - Distributed) A remote is a reference to another repository through a network A clone is a copy of a repository: it contains all the objects from the original.
git clone url_to_a_repository It copies all the objects from the remote repo into a local repository It maintains a link to the original via a remote called origin The remote repo doesn’t know anything about its clones
remote The git remote command is useful to manage the remotes add, rm , show Multiple remotes can exist: central repo production test
fetch, pull and push fetch retrieves objects and related metadata from a remote repository pull like fetch plus merge changes into a corresponding local branch push transfer local objects and metadata to a remote repository
git push [-u] origin branch_name fetch, pull and push Used to sync with remote repositories (usually the central repository) Flow: Work locally Push commits to the remotes git push [-u] origin branch_name
Submodules It’s a tool to import in the current repository dependencies or other libraries that are useful for the project (SVN Externals)
submodule git submodule add /path/to/repo sub_name It clones the repo and create a .gitmodule file with module information [submodule "rack"] path = rack url = git://github.com/chneukirchen/rack.git
submodule When a repo with submodule is cloned two additional commands must be issued: git submodule init git submodule update
Daily use Different branch for environment/customer Branch per feature Tags for version
Gitflow http://nvie.com/posts/a-successful-git-branching-model/
GUIs Don’t underestimate the power of the command line But sometimes GUIs are better (especially for diff and log) VS2015/2017 has the git plugin
http://www.sourcetreeapp.com/
https://windows.github.com/
some useful commands Permanently remove a file from the history: git filter-branch --tree-filter 'rm -rf file_to_delete’ HEAD
some useful commands Delete a remote branch git push origin :nome_del_branch git push –-delete origin nome_del_branch
some useful commands Push from one branch to another git push <remote> <local_branch_name>:<remote_branch_to_push_into >
some useful commands Sync the local branch list with remote git remote prune origin
some useful commands list the most touched files git log --pretty=format: --name-only | sort | uniq -c | sort -rg | head -10
some useful commands Show a file on a specific branch git show feature1:file1.txt
The end