Gitting More Out of Git
#Jordan Kasper
Disclaimers – not for noobs, all examples will be from the command line
Git is decentralized. We all know that, but do we know what it really means?
The entire repo is on your system – not just the branch you are working on
Including all of the history
So, if the “central” goes down, you can still work. In fact, other people can get it from you as well to start working. We don’t typically do that, though.
Remotes
A remote is repository outside of your current environment. Technically even in another location on you system.
When you clone, you get all branches. It also creates a remote named “origin” that points to the location you cloned from.
Your local branch is “tracking” the remote branch. This is how git knows where to send your changes to when you do a push.
git remote -v will tell you where all of your remotes point
git push -u origin new-feature will set the “upstream” remote branch to track your local branch to
Forking is a github term, not a git thing
A fork is actually just a case of setting a remote
git fetch <remotename> will pull down changes from a specific remote (default is usually origin)
fetch gets all of the changes
pull gets them AND merges into your code
Branches
git branch –no-merged will show you all of the branches that have not yet been merged
git diff master stuff is essentially how a pull request works
git diff master..stuff shows the differences between the branches from when the branch split from master
Git and Data Integrity
Git uses snapshots (not file diffs)
File diffs means differences are tracked by file
Snapshot is a picture of the entire repo when taken (all files) – marked with a hash of the entire repo at that time – even changing a single whitespace character will be noted (because you get a different hash)
Hash is actually 40 characters of hexidecimal. You usually only see 7 because that is enough to be distinct in most cases.
When things go Wrong
git commit –amend -m “corrected message” will allow you to correct a commit message, but note that it changes the hash, since you changed the metadata
YOU SHOULD NEVER CHANGE COMMITS YOU HAVE ALREADY PUSHED TO A SHARED REPOSITORY
Two changes with the same things changed but different hashes will cause problems, that is why you should not change a commit after you have shared (pushed) it
reflog is local to you – it is never shared
git reflog shows your changes over time
You can even add a file to a commit: git commit –amend (after staging the file) (Again, don’t do this after you have pushed)
git checkout <filename> will throw away your unstaged changes. It will not remove a newly added file, however.
Three stages of a git repo
HEAD – commited code
Staging – ready to commit
Working Directory – your current work
Committed Changes (oops)
git reset –soft HEAD^ (move head back one commit (more ^’s means more commits))
git reset –mixed HEAD^ (moves head AND staging back one commit)
git reset –hard HEAD^ (wipes out the change completely from all three stages)
you can still get your changes back if you find out you didn’t mean to use “hard”
use git reflog to find the hash for the deleted commit:
git reset HEAD@{1} will bring the change back
THIS IS ONLY LOCAL
Once you have any changes pushed beyond your local repo you should consider it carved in stone. You should not make these kinds of changes to pushed commits.
Head Notation
HEAD^ (back one from current HEAD)
HEAD^^ (two places)
HEAD~n (back n places)
HEAD@{i} (back to reflog index ‘i’)
git stash
You made some changes, but you aren’t ready to commit. Now you need to do work in a different branch. Changing branches will bring along unstaged changes. stashing puts your changes out of your way
You actually have to stage first (most people don’t know that)
git stash will “commit” all staged (and maybe unstaged) changes to a temporary local commit and restore your working environment to the last commit
you can stash multiple times
git stash list shows your currently stashes
BUT – it doesn’t have any comment
git save lets you comment
git stash apply brings it back, but doesn’t get rid of it
git stash drop will remove them
git stash pop brings out your stash and removes it from your list of stashes
Log Options
git log –oneline shows you one line
git log –online –graph shows you a command line version of the pretty branch chart most GUI tools have
git log has lots of options to only show you want you want
Blame
git blame filename will show you the last change for each line (hash, author, line)
Playing Nice with Others
git checkout master
git merge feature
Fast forward if no divergent changes
Fast forward does not put the fact that there was a merge in the history
–no-ff forces a merge commit so you can see a merge happened
If there are divergent changes, you get a merge commit (which has 2 parents – only kind of commit with multiple parents)
Merge conflicts – changes git can’t sort out (both commits change the same line for example)
Fix the problem file
Stage the file
Commit (which will be the merge commit)
Rebase
Rewrites history
Essentially changes the commit you branched from. Doing this one already pushed changes will cause problems, same as above.
You can still get comflicts in a rebase, handled the same way, except you tell rebase you want to continue (problems pause a rebase)
git rebase –abort allows you to stop a rebase if there is an issue
Cherry Picking
Allows you to bring in changes from a different branch that has some work you want to save. After you cherry pick, you should delete the branch you cherry picked from.