Advanced Git
-
Upload
sergiu-ioan-ungur -
Category
Software
-
view
263 -
download
0
Transcript of Advanced Git
Overview
Version Control System (VCS)● Merging● Time capsule
Distributed Version Control System (DVCS)● Central repository● Local copy of the repository
Origins
Linus Torvalds (2005)● Linux Kernel project.● Meant to be distributed, fast and more
natural.● Capable of handling large projects.
Contents
1. Merging vs. Rebasing2. Reset, Checkout, and Revert3. Advanced Git log4. Git Hooks5. Refs and Reflog6. Git Aliases7. References
1. Merging vs. Rebasing
$ git rebase● magical Git voodoo● solve the same problem as git merge:
integrate changes from one branch into another branch
Merge option
$ git checkout feature$ git merge master________________________________________$ git merge master feature
Merge option
● Results in a new “merge commit”.
● Merge is “nice” (non-destructive).
● But... it pollutes your feature branch’s history.
Rebase option
$ git checkout feature$ git rebase master
● Results in moving the entire feature branch to begin on the tip of the master branch.
Rebase option
● Rebasing re-writes the project history.
● A much cleaner project history: perfectly linear project history.
Interactive rebasing
● Complete control over the branch’s commit history.
● Clean up a messy history before merging a feature branch into master.
$ git checkout feature$ git rebase -i master
Interactive rebasing
pick 33d5b7a Message for commit #1pick 9480b3d Message for commit #2pick 5c67e61 Message for commit #3
pick 33d5b7a Message for commit #1fixup 9480b3d Message for commit #2pick 5c67e61 Message for commit #3
Golden Rule of Rebasing
Before you run git rebase, always ask yourself: Is anyone else looking at this branch?
Force-Pushing
# Be very careful with this command!$ git push --force● Overwrite the remote master branch to
match the rebased one from your repository.
● One of the only times to use force-pushing: local cleanup on a private feature branch.
Local Cleanup
● Make sure each commit in your feature is focused and meaningful.
● Two options for the new base:■ the feature’s parent branch (e.g. master)■ an earlier commit in your feature
● For instance, we need to fix up the last few commits.
Local cleanup
$ git checkout feature$ git rebase -i HEAD~3To re-write the entire feature, use:$ git merge-base feature master
Incorporate upstream
Let assume that you want to fetch the John’s changes in to your feature branch.
Integrate a feature
After a feature has been approved by your team:
● rebase the feature onto the tip of the master
● then, use git merge to integrate the feature into the main code base
Summary
$ git rebase● clean, linear history free of unnecessary
merge commits$ git merge
● preserve the complete history● avoid the risk of re-writing public
commits
2. Reset, Checkout, Revert
git reset, git checkout, and git revert● some of the most useful tools in your Git
toolbox● all let you undo some kind of changes● the first two can be used to manipulate
either commits or individual files
Commit-level Operations
● The parameters you pass to git reset and git checkout determine their scope.
● When you don’t include a file path as a parameter, they operate on whole commits.
● Note: git revert has no file-level counterpart.
Reset
● Move the tip of a branch to a different commit.
● Usage: e.g. remove commits from the current branch.
$ git checkout hotfix$ git reset HEAD~2
Reset
Flags:● --soft - staged snapshot, working
directory.● --mixed - staged snapshot, working
directory. Default option.● --hard - staged snapshot, working
directory.
Checkout
● Switch between branches:$ git checkout hotfix
● Internally, it moves HEAD to a different branch and update the working directory to match.
Revert
● Undo a commit by creating a new commit.● Safe way to undo changes.
$ git checkout hotfix$ git revert HEAD~2
File-level Operations
git reset and git checkout● accept an optional file path as a
parameter● this dramatically alters their behaviour● limit their operations to a single file
Reset
● Update the staged snapshot to match the version from the specified commit.
$ git reset HEAD~2 foo.py● Fetch the version of foo.py in the 2nd-to-
last commit and stage it for the next commit.
Reset
Notes:● --soft, --mixed, and --hard flags do not
have any effect on the file-level version of git reset
● staged snapshot is always updated● working directory is never updated
Checkout
● Similar to using git reset with a file path, except it updates the working directory instead of the stage.
$ git checkout HEAD~2 foo.py● Make foo.py in the working directory
match the one from the 2nd-to-last commit.
Summary
Command Scope Common use cases
git reset Commit-level Discard commits in a private branch or throw away uncommited changes.
git reset File-level Unstage a file
git checkout Commit-level Switch between branches or inspect old snapshots
git checkout File-level Discard changes in the working directory
git revert Commit-level Undo commits in a public branch
git revert File-level N/A
3. Advanced Git log
1. Formatting how each commit is displayed.2. Filtering which commits are included in the
output.
=> go back into your project and find any information that you could possibly need
Formatting Log Output
Oneline$ git log --oneline
0e25143 Merge branch 'feature'ad8621a Fix a bug in the feature16b36c6 Add a new feature23ad9ad Add the initial code base
Formatting Log Output
Decorating$ git log --oneline --decorate
0e25143 (HEAD, master) Merge branch 'feature'ad8621a (feature) Fix a bug in the feature16b36c6 Add a new feature23ad9ad (tag: v0.9) Add the initial code base
Formatting Log Output
Diffs$ git log --stat
commit f2a238924e89ca1d4947662928218a06d39068c3Author: John <[email protected]>Date: Fri Jun 25 17:30:28 2014 -0500
Add a new feature
hello.py | 105 ++++++++++++++++++++++++----------------- 1 file changed, 67 insertion(+), 38 deletions(-)
Formatting Log Output
Diffs$ git log -p
commit 16b36c697eb2d24302f89aa22d9170dfe609855bAuthor: Mary <[email protected]>Date: Fri Jun 25 17:31:57 2014 -0500
Fix a bug in the feature
diff --git a/hello.py b/hello.pyindex 18ca709..c673b40 100644--- a/hello.py+++ b/hello.py@@ -13,14 +13,14 @@ B-print("Hello, World!")+print("Hello, Git!")
Formatting Log Output
The Shortlog$ git shortlog [-n]
Mary (2): Fix a bug in the feature Fix a serious security hole in our framework
John (3): Add the initial code base Add a new feature Merge branch 'feature'
Formatting Log Output
Graphs$ git log --graph --oneline --decorate
* 0e25143 (HEAD, master) Merge branch 'feature'|\ | * 16b36c6 Fix a bug in the new feature| * 23ad9ad Start a new feature* | ad8621a Fix a critical security issue|/ * 400e4b7 Fix typos in the documentation* 160e224 Add the initial code base
Formatting Log Output
Custom Formatting$ git log --pretty=format:"%cn committed %h on %cd"
John committed 400e4b7 on Fri Jun 24 12:30:04 2014 -0500John committed 89ab2cf on Thu Jun 23 17:09:42 2014 -0500Mary committed 180e223 on Wed Jun 22 17:21:19 2014 -0500John committed f12ca28 on Wed Jun 22 13:50:31 2014 -0500
https://www.kernel.org/pub/software/scm/git/docs/git-log.html#_pretty_formats
Filtering Commit History
● By amount:$ git log -3● By date (--after/--since, --before/--until):$ git log --after="2014-7-1"$ git log --after="yesterday"$ git log --after="2014-7-1" --before="2014-7-4"
Filtering Commit History
● By author (--author, --committer):$ git log --author="John"$ git log --author="John\|Mary"● By message:$ git log --grep="JRA-224:"● By file:$ git log -- foo.py bar.py
Filtering Commit History
● By content (pickaxe):$ git log -S"Hello, World!"● By range:$ git log <since>..<until>$ git log master..feature
Conceptual Overview
Git Hooks● ordinary scripts that Git executes when
certain events occur in the repository● local repository● server-side repository
Conceptual Overview
Installing Hooks● .git/hooks directory
applypatch-msg.sample pre-push.samplecommit-msg.sample pre-rebase.samplepost-update.sample prepare-commit-msg.samplepre-applypatch.sample update.samplepre-commit.sample
Conceptual Overview
Simple prepare-commit-msg hook:● Remove the .sample extension.● Add
#!/bin/shecho "# Please include a useful commit message!" > $1
● Executechmod +x prepare-commit-msg
Conceptual Overview
Scripting Languages● built-in scripts: shell and PERL● you can use any scripting language you
like as long as it can be run as an executable
● shebang line #!/bin/sh
Local Hooks
The most useful local hooks:● pre-commit● prepare-commit-msg● commit-msg● post-commit● post-checkout● pre-rebase
Summary
● The hooks let us plug in to the entire development life cycle.
● Perform customizable actions at every stage in the commit creation process, as well as the git push process.
Hashes
● The most directly way to reference a commit is via its SHA-1 hash.
$ git show 0c708f● Resolve a branch, tag or another indirect
reference into the corresponding commit hash.
$ git rev-parse master
Refs
● A ref is an indirect way of referring to a commit (alias).
● Refs are stored in .git/refs directory:.git/refs/ heads/ master some-feature remotes/ origin/ master tags/ v0.9
Specifying Refs
● Passing a ref to a Git command:■ full name of the ref■ short name of the ref
$ git show some-feature● Git resolves some-feature to
refs/heads/some-feature$ git show refs/heads/some-feature
Packed refs
● Git garbage collection => compress refs into a single file
● Force the compression:$ git gc
● .git/packed-refs00f54250cf4e549fdfcafe2cf9a2c90bc3800285 refs/heads/feature0e25143693cfe9d5c2e83944bbaf6d3c4505eb17 refs/heads/masterbb883e4c91c870b5fed88fd36696e752fb6cf8e6 refs/tags/v0.9
Special Refs
● HEAD - The currently checked-out commit/branch.
■ HEAD can contain either a symbolic ref or a commit hash.
● FETCH_HEAD - The most recently fetched branch from a remote repo.
● ORIG_HEAD - A backup reference to HEAD before drastic changes to it.
Special Refs
● MERGE_HEAD - The commit(s) that you’re merging into the current branch with git merge.
● CHERRY_PICK_HEAD - The commit that you’re cherry-picking.
Refspecs
● A refspec maps a branch in the local repository to a branch in a remote repository.
● Specified as [+]<src>:<dst>● <src> - source branch● <dst> - destination branch● + - forcing the remote repository to perform
a non-fast-forward update
Refspecs
● Specify the remote branch:$ git push origin master:refs/heads/qa-master
● Remove a remote branch:$ git push origin :some-feature$ git push origin --delete some-feature
Refspecs
● .git/config[remote "origin"] url = https://[email protected]:mary/example-repo.git fetch = +refs/heads/*:refs/remotes/origin/*
[remote "origin"] url = https://[email protected]:mary/example-repo.git fetch = +refs/heads/master:refs/remotes/origin/master
[remote "origin"] url = https://[email protected]:mary/example-repo.git fetch = +refs/heads/master:refs/remotes/origin/master push = refs/heads/master:refs/heads/qa-master
Refspecs
● Refspecs gives you complete control over how various Git commands transfer branches between repositories.
● Rename/delete branches.● Fetch/push to branches with different
names.● Configure git push and git fetch to work
with only the branches that you want.
Relative Refs
● Refer to commits relative to another commit:
$ git show HEAD~2
● ~ - Follow the first parent of a merge commit.
● ^ - Specify the parent you want to follow.$ git show HEAD^2$ git show HEAD^2^1
Relative Refs
# Only list commits that are parent of the second parent of a merge commit$ git log HEAD^2
# Remove the last 3 commits from the current branch$ git reset HEAD~3
# Interactively rebase the last 3 commits on the current branch$ git rebase -i HEAD~3
The Reflog
● Git’s safety net.● Record almost every change you make in
your repository$ git reflog400e4b7 HEAD@{0}: checkout: moving from master to HEAD~20e25143 HEAD@{1}: commit (amend): Integrate some awesome feature into `master`00f5425 HEAD@{2}: commit (merge): Merge branch ';feature';ad8621a HEAD@{3}: commit: Finish the feature
The Reflog
● HEAD{<n>} - Reference commits stored in the reflog.
● Revert to a state that would otherwise be lost.
ad8621a HEAD@{0}: reset: moving to HEAD~3298eb9f HEAD@{1}: commit: Some other commit messagebbe9012 HEAD@{2}: commit: Continue the feature9cb79fa HEAD@{3}: commit: Start a new feature
The Reflog
● “Oups, I shouldn’t have done that!”● “Don’t worry :) !”
$ git checkout HEAD@{1}
● Note: this puts you in a detached HEAD state.
Summary
● Git reflog - a way to reference commits that are not available through any other means.
● The point of all this was to be able to pick out exactly the commit that you need in any given development scenario.
6. Git Aliases
● https://github.com/ssergiuss/dotaliases
7. References● https://www.atlassian.com/git/tutorials/merging-vs-rebasing● https://www.atlassian.com/git/tutorials/resetting-checking-out-
and-reverting● https://www.atlassian.com/git/tutorials/git-log● https://www.atlassian.com/git/tutorials/git-hooks● https://www.atlassian.com/git/tutorials/refs-and-the-reflog● http://www.vogella.com/tutorials/Git/article.html● https://github.com/ssergiuss/dotaliases