Github Webinar - 2012.01.10¶
Session 1 (8:00a - 8:50a)¶
Introduction, a little history.
git init <projectname>
.git folder contains entire commit history
user identity - separate from auth, merely who you are.
locally, there are no permissions present other than those of the filesystem itself.
- git config
–local = per repository –global = per user –system = per machine
color.ui auto
core.autocrlf input – “This setting tells git to convert the newlines to the system’s standard when checking out files, and to LF newlines when committing in”
ssh-keygen -t rsa -C”<email> for <purpose>”
-C = comment
Session 2 (9:00a - 9:50a)¶
Committing code
Files being bumped out of stage (editing a file once it’s staged)? Not really. What really happens? Why is the file shown in unstaged and staged? There are two sets of changes. Two scopes, file and content. Git separates them in to two sets of changes – to see the difference:
git diff
compare to
git diff --staged
to see what’s going on.
git commit -v
Interatcive add:
``git add -p``
Filtered Diff:
``git diff -diff-filter=M``
A = Added C = Copied D = Deleted M = Modified R = Renamed T = Type changed U = Unmerged X = Unknown B = Broken pairing
Normal git diff
– highlights whitespace changes.
git diff -w
– surpresses whitespace changes.
git diff --color-words HEAD
git add -A
– adds any new files whereas git add .
will just add modified.
Session 3 (10:00a - 10:50a)¶
Viewing history
Git log¶
No options: reverse chronological order. Automatically piped to pager.
Rarely used with no options.
git log --stat
– shows files that participted in each commit. Commit hash, author, date, files, +/- for lines per change.
Extremely tedius to page our way back through changes.
Milestone marker for class: if we stopped now, you should have a pretty good basic workflow for getting around day-to-day.
More advanced usage:
``git log --diff-filter=A`` -- Same filters as ``git diff``
git log --pretty=raw
– raw, full, fuller, and even custom with sprintf
git log -3
– limits number of commits to 3 in this case.
git log --author=evan@wiredrive.com
– all commits authored by me.
git log --author=Evan
– all commits by me by using my name.
Ignoring Files¶
Flat text file called .gitignore
Per project: in project root
Example:
*.log
*.tmp
Ignores all files with .log and .tmp exensions.
Note
git status -u
– show me all files, don’t simplify, lists out all files below folders.
Applies, at evaluation time in memory.
You can add .gitignore files to subfolders, behave like .gitconfig:
Top has weakest precidence, bottom has highest precidence.
They’re evaluated as if concatenated end-to-end.
.gitignore can exist in any number of directories and subdirectories with no limit.
Git does not track empty directories.
How do you track empty directories? “holding it open with a toothpick.”
Usually the easiest way is to touch a .gitignore in that directory.
Preconfigured .gitignore files: https://github.com/github/gitignore
System-wide?
git config --global core.excudesfile "~/.gitignore"
Have to enable, can’t just create the file.
Removing Files¶
Closure to the add command
Basis for refactoring and renaming
rm <filename>
git rm <filename>
– put deletion into staging, if file doensn’t exist, just adds deletion to staging area
- example::
- rm <files> git add -u .
git add -u
grabs all removed files.
git rm <fileame>
removes the file and stages that file.
If you want it back:
git reset --hard
– we’ll come back to this, but it returns everything that is tracked to their last committed state. Blows away everything that’s staged.
note: untracked files are untouched.
There is no move
primitive in git.
git mv <src> <dst>
– a ‘composed’ command for convenience.
Same as:
``mv <src> <dst> ; git add <dst>``
Rename flagged as soon as file is re-added. Git is good at detecting similar content.
There’s a pretty funny discussion on the git mailinglist as to why there is no move primitive. Might be worth a look. (See slides).
git log --stat -M
– shows renames in history.
Mindset should be that no matter how accurate we are when committing to history, there’s always a chance that the committer has been mistaken at commit time. Just move it to the display layer.
Q: Can you set a threshold on the similarity filter?
A: Yes, git log --stat -M90
.
git log -2 --stat -C --find-copies-harder
– Tells it to look harder for copy detection on top of rename detection.
This stuff can be used for the simplification of merges and is relevant for refactoring.
Session 4 (12:00p - 2:00p)¶
Questions¶
- Can you reset an individual file?
git checkout -- <filename>
git checkout HEAD -- source/
What’s the difference between
git checkout -- <filename>
and
git checkout HEAD -- <filename>
Nothing, HEAD is assumed.
- Other questions on collaboration, binaries and design...
Netork Interactions¶
Everything begins locally in git then layers on things like remotes and collaboration.
Almost all activities happen offline. Offline activities have to be pushed to remotes.
Cloning¶
four primary protocols: file, git, ssh, http.
file¶
git clone file:///path/to/project
git clone /path/to/project
cloning a local file is like checkout, but clone grabs all history for a repository.
file:///path/to/project fires up the ‘networking’ code within git whereas just /path/to/project looks directly at the filesystem.
git¶
git clone git://server/project.git
Almost always read-only. Can be made writable, but in most cases it’s read-only.
http (dumb)¶
git clone http://server/project.git
git clone https://server/project.git
Used to be the real differntiator between git and mercurial. Dumb version is insanely slow and inefficient.
https (smart)¶
Much faster and offers progress. Mostly handled on the server side.
Exercises¶
Cloning and collaborating:
git clone https://githubstudents:students987@github.com/githubstudents/hellogitworld.git
git branch evanculver
git push -u
– tells git to track it.
<BREAK>
Example of git’s speed by adding 3000 files and pushing them to remote.
After pushing, we can almost instantly get references to those files, but they’re just references.
git fetch origin
git checkout thousands
When checking out, the state of the filesystem is being modified. By switching between the thousands
branch and mine, > 3000 files are being created/destroyed
“Once mastered, the concepts of local, remote and upstream branches, the rest falls into place”
Local and remote live on your box.
Typing git fetch
, your local cache is updated against what’s upstream or remote to you.
git fetch
=== git fetch origin
Push¶
git push <remote>
Pull¶
0 collaboration up until this point. The integration point.
Combination: retrieves upstream objects and then merges and then commits merge to the local branch.
Excercise: Merging in remotes¶
Merging:
git merge remotes/origin/chance
Pushing back up to remote:
git push
Reviewing any commits in the entire remotes tree:
git log -2 remotes/origin/chance
Remotes¶
Simiply ‘bookmarks’ or pointers.
Origin is a remote you get by default.
git remote -v
Q: Why two entries? A: One inbound and one outbound. Almost always the same, but can be different in a very unique situation. For example, you may want to pull all code over ssh but push all over http.
Adding a remote¶
git remote add <remotename> <remotepath>
git remote add matthewongithub https://github.com/matthewmccullough/hellogitworld
note: Remote branches are locally immutable.
We have to make a local branch for anything we would like to change.
git checkout kenkil
Git is smart enough to know that you probably wanted to actually checkout the remote (remotes/origin/kenkil
).
If you look at .git/config
, you will see various [branch *]
sections which define the remote/tracking portion of this.
Git will get mad if the branch name is ambiguous:
error: refspec... blah blah
git checkout -b <localbranch> --track remotes/origin/richzurad
Prune¶
git remote prune <remotename>
– only removes old branches that no longer exist on the remote, has to be given an explicit remote name.
Diff’ing against remotes (or any two things)¶
git diff origin/ericg
git diff origin/ericg origin/richzurad
More exercises¶
<edit, add, commit>
git reset --soft HEAD~1
Tells git to roll back 1 commit, leaving the change in tact.
If you have already pushed, the game has changed entirely.
You can do the same as above, but force the push – the consequences of forcing the push causes the graph of the commits changes as your peers see them. Furthermore, you then have to ask what other people may be basing their work on. It may cause some really counter-intuitive output and attempts to merge in changes.
A better approach is to push another commit by ‘reverting’:
git revert <commithash>
– Make a new commit that negates what was just committed. Always safe because it’s always forward moving which is exactly why forcing commits and changing history/graphi is usually always bad.
Session 5 (2:15p - 2:15p)¶
Creating a funky situation¶
git checkout -b evanculver2
<edit a particular line>
<add, commit>
git checkout -b evanculver
<edit same line as before>
<add, commit>
git merge evanculver2
EEEEK –> merge conflict
“Make the file appear as a logical combination of those two disparate pieces”
Pull requests and workflow¶
Pull requests aren’t limited to cross-repository merges. Pull requests make perfect sense within a single repository for forced code-review.
Rebase¶
Simulates members taking turns working? Actually not stupid, just sounds ridiculous.
Branching: you usually wait as long as possible to branch, and you try to get your changes merged back in as soon as possible (because your VCS sucks).
Rebasing rewrites history, keeps a consistent, straight history.
Merge commits become integration commits by layering merges on to the end via fast-forward (instead of merge made by recursive).
Fast-forward means that only one of the two branches changed since the branch occurred.
No merge commits are created.
git checkout feature/some-feature
git rebase master
“Take all of the stuff in the feature branch, hibernate it, delete it, start it at the end of master then replay all of the work in the feature branch on master.”
“Rework your work so that it makes more sense for your team.”
git checkout feature/some-feature
git rebase -i HEAD~5
“Rebase seems like a tool to replay history.”
Gist created by Matt with his notes: