Get Started with Git

Get Started with Git

In this tutorial, we'll start from zero and build your knowledge step-by-step about how to use Git effectively. We'll start with the basics of creating a repository and making commits, and move on to branching, merging, resolving conflicts, and generally moving commits around. Next, we'll cover the most popular options for hosting repositories online (GitHub, GitLab, and BitBucket), and how to interact with other peoples' Git repos on those websites.

Then we'll start getting into more advanced topics. You'll learn about rebase, and its awesome power to travel through time and re-write the history of your project. You'll also learn how to wield that power with restraint and recover from your mistakes, so that you can use it safely and confidently. Once you've learned how to rebase, you'll be able to split and combine commits, fix up poorly-written commit messages, remove passwords from your history before they were ever mistakenly committed, or even make it look like you wrote perfect code the first time.

You'll also learn how to be more productive with Git by integrating it into your everyday development tools, like your text editor and your shell. (Being able to constantly see what branch you're working on is a huge help!) You'll also learn how to streamline your workflow by using Git's event hooks to run arbitrary scripts for you, and how to take advantage of the integrations provided by your online host of choice.

Presented at PyCon 2016: https://us.pycon.org/2016/schedule/presentation/1620/

42c77de97965d620ba0b6ae624c3ba7b?s=128

David Baumgold

May 28, 2016
Tweet

Transcript

  1. 2.

    PRE-WORK ➤ Install Git ➤ Install a text editor with

    shell commands (Atom is a good choice) ➤ Optional: Install zsh and oh-my-zsh ➤ Learn how to use the command line ➤ Make an account with GitHub.com ➤ Optional: Make an account on GitLab.com If you have not already done these things, you should go to https://github.com/singingwolfboy/git-tutorial-prework and do them!
  2. 3.

    Elisabeth Robson & Eric Freeman A learner’s guide to Git

    Head First Git David Baumgold A Brain-Friendly Guide Learn how to travel through time Editing has never been so enlightening Compatible with all kinds of text, not just software Track down issues at their source Discover the freedom in branching, forking, & merging Change history without tying yourself in knots
  3. 4.

    WHAT IS VERSION CONTROL? ➤ Ability to always go back

    to an old version ➤ Track metadata about changes: who, when, and why? ➤ Allow multiple editors to make changes simultaneously without stepping on each others’ toes Sadly, version control is not often taught in school. Therefore, I will assume that this is all new for you. If you’ve done version control before: great! Refresh your knowledge.
  4. 5.

    Central Repository Partial copy Partial copy Partial copy Partial copy

    changes CENTRALIZED VCS ➤ One central repository ➤ Many partial copies, one for each editor ➤ Partial copies can download updates from central repo, and send changes to central repo (if changes don’t conflict) ➤ Partial copies never talk to each other directly ➤ Examples: CVS, Subversion, ClearCase, Perforce
  5. 6.

    Repo Repo Repo Repo Repo Repo DECENTRALIZED VCS ➤ Every

    editor has a copy of the entire repository, including all history for the project ➤ Every repo has its own owner & permissions: forking is common ➤ Central repository is not necessary — however, some teams choose to designate one repo as the “main” one ➤ Examples: Git, Mercurial
  6. 7.

    AGENDA ➤ Create your own Git repo, make commits to

    track changes ➤ Collaborate with others by pushing and pulling changes between repos, making pull requests, and merging them ➤ Learn about Git’s branching model and how to work on multiple changes simultaneously ➤ Move commits around between branches,
 move branches around within repos ➤ Travel through time and change history in your repo
  7. 9.

    MAKE A REPO $ git init cookbook ➤ git init

    creates a new, empty repo ➤ Optional argument is the name of the directory to create;
 otherwise the repo will be created in the current directory ➤ Creates a .git directory that stores all the repo information
  8. 10.

    EXPLORE THE REPO $ ls .git HEAD info/ config objects/

    description refs/ hooks/ Mostly, you shouldn’t need to touch the contents of the
 .git directory, but there is one very useful file: .git/config
  9. 11.

    GIT CONFIG $ git config <key> [<value>] ➤ git config

    allows you to read and write values
 to Git’s config files ➤ By default, it uses .git/config
 Use the --global flag to use ~/.gitconfig ➤ You’ll need to set your name and email address: $ git config --global user.name "Joe Developer"
 $ git config --global user.email "joe@example.com"
  10. 12.

    MAKE A FILE ➤ Find a delicious recipe, copy the

    text, paste it into a file
 in your “cooking” Git repo. For example: S'mores Recipe Ingredients: 1 large marshmallow 1 graham cracker 1 bar of chocolate Directions: 1. Heat the marshmallow over an open flame
 until it begins to brown and melt. 2. Break the graham cracker in half.
 Sandwich the chocolate between the cracker
 and the hot marshmallow. Allow the marshmallow
 to cool a moment before eating. smores.txt
  11. 13.

    GIT STATUS $ git status ➤ git status tells you

    the status of the files in your repo:
 what is new, what has changed, what’s been deleted ➤ git status is always safe to run, and will never change
 or break anything in your repo ➤ My most frequently used Git command!
  12. 14.

    GIT ADD $ git add smores.txt ➤ git add tells

    Git that you want a certain file added to the
 repository in an upcoming commit ➤ Marks the file to be included as it is at that point in time.
 Picks up on changes since the last commit, but won’t pick
 up on changes you make after running git add — you’ll
 need to re-add the file to include those changes! ➤ Adding a directory will add all files in that directory.
 Use git add . to add all files at once!
  13. 15.

    GIT COMMIT $ git commit ➤ git commit creates a

    new commit based on the files
 you’ve marked using git add ➤ A commit message is required: Git will open your text
 editor so you can write one ➤ You can use the -m flag to provide a message on the
 command line, instead
  14. 16.

    COMMITTING CHANGES To commit a change to the repo, do

    the following: ➤ Edit files and save changes ➤ git add <files> ➤ git commit Special case: to delete a file from the repo, use $ git rm <file> exactly like how you would use git add
  15. 17.

    COMMANDS FOR MAKING COMMITS ➤ git init ➤ git status

    ➤ git add <file> ➤ git rm <file> ➤ git commit
  16. 18.

    VIEWING THE COMMIT LOG $ git log ➤ git log

    displays a log of all the commits,
 from most recent to least recent ➤ Use the arrow keys to scroll, press “Q” to quit
  17. 19.

    GIT SHOW $ git show <hash> ➤ git show displays

    detailed information about a particular commit ➤ The hash argument is optional, defaults to current commit ➤ Use the arrow keys to scroll, press “Q” to quit
  18. 20.

    VIEWING A DIFF $ git diff ➤ git diff shows

    the changes you’ve made that haven’t yet
 been committed ➤ Useful for checking to be sure that you’ve made all the
 changes you intend, and none of the ones you didn’t ➤ Use the --staged argument to view changes that you’ve
 already added using git add ➤ Use the arrow keys to scroll, press “Q” to quit
  19. 21.

    BROWSING HISTORY $ git checkout <hash> ➤ git checkout allows

    you to view your project
 as it was at a particular commit ➤ You will get a big scary “detached HEAD” warning:
 ignore it for now ➤ To get back to your most recent commit, use master
 instead of a hash, like this: $ git checkout master Do this before making any new commits!
  20. 22.
  21. 23.

    ALL THE GIT COMMANDS WE KNOW SO FAR git log

    git show git diff git checkout git init git config git status git add git rm git commit making commits viewing commits
  22. 25.

    CREATE REPO ON GITHUB ➤ Visit GitHub.com, log in, and

    click on the plus sign at the top to make a new repository
  23. 26.
  24. 27.
  25. 30.

    GIT REMOTES $ git remote add <name> <url> ➤ git

    remote creates short nicknames for URLs that point to
 other Git repos that you want to share commits with ➤ Run git remote -v to list all the remotes that the repo knows about ➤ Remotes are saved in the .git/config file: you can edit it, if you want
  26. 31.

    GIT PUSH $ git push ➤ git push sends commits

    from your repo to another repo ➤ Can specify a remote; if not, pushes to whatever remote is set as default $ git push -u origin master This is what GitHub tells you to run ➤ -u origin sets the “origin” remote as the default remote ➤ master is a branch, and it’s the same thing we use to get back to the
 most recent commit. We’ll learn about branches in a little bit.
  27. 33.

    GIT PULL $ git pull ➤ git pull gets commits

    from another repo to your repo, and updates
 your files with those changes ➤ Can specify a remote; if not, pulls from whatever remote is set as default git fetch git merge + “fetch” is what downloads commits. “fetch” never changes the files on
 your computer, even if the commits
 say the files should change. “merge” is what updates files. We’ll learn more about “merge”
 on the next slide
  28. 34.

    GIT FETCH $ git fetch <remote> ➤ git fetch downloads

    information from a remote, but
 does not change any files in your repo ➤ Run automatically as part of git pull ➤ The equivalent of saying: “Hey remote, tell me what’s new
 since we last saw each-other!”
  29. 35.

    GIT MERGE $ git merge <remote>/master ➤ git merge combines

    the commits
 on a remote repo with the commits
 on your local repo ➤ Creates a new commit that has
 multiple parents: called a
 “merge commit” ➤ In the diagram, every commit has
 a black pointer to its parent. We’ll
 talk about those more later. local remote merge most recent commits oldest commits
  30. 36.

    GIT CLONE $ git clone <url> ➤ git clone makes

    a local copy of a repo
 that is available at the given URL ➤ The local copy is a full, complete repo,
 with all commits and history ➤ Local copy has a remote named origin,
 which is set to the original URL ➤ The local copy is yours: you can change it
 however you want! Taking an existing project and making your own changes
 is called “forking”, and it happens all the time with Git
  31. 37.

    COMMANDS FOR COLLABORATION ➤ git clone ➤ git remote ➤

    git push ➤ git pull ➤ git fetch ➤ git merge
  32. 38.

    ALL THE GIT COMMANDS WE KNOW SO FAR git clone

    git remote git push git pull git fetch git merge git log git show git diff git checkout git init git config git status git add git rm git commit making commits viewing commits collaborating
  33. 39.

    RUNNING INTO PROBLEMS ➤ Clone the repo at
 https://github.com/singingwolfboy/tutorial-cookbook ➤

    Create a new file in the repo with a new recipe. Write out your favorite recipe, or find a random one on Google and copy-paste it in. ➤ Commit your new recipe, and try to push it up to the GitHub repo you that cloned from! (Spoiler alert: it won’t work. Why not? What is the error message?)
  34. 40.

    PULL REQUESTS 1. Fork the repo, so you have control

    over your fork 2. Make commits in your fork to change it however you want 3. Contact the owner of the upstream repo, show your changes, ask the owner to pull your changes into upstream repo GitHub has a special interface for managing these requests,
 which they call Pull Requests
  35. 41.
  36. 42.
  37. 43.

    MAKING PULL REQUESTS ➤ Fork the repo at
 https://github.com/singingwolfboy/tutorial-cookbook ➤

    Clone your forked repo to your computer ➤ In your forked repo, create a new file with a new recipe, and commit it ➤ Push your commit to your fork on GitHub ➤ Make a pull request from your fork to my repo (known as the “upstream” repo)
  38. 44.

    MERGING PULL REQUESTS ➤ Can use the merge button on

    a GitHub pull request ➤ OR, do it manually with Git: ➤ Add requester’s fork as a remote ➤ git fetch <remote> ➤ git merge <remote>/master ➤ git push ➤ GitHub will automatically update the pull request! Remember, “git pull” is “git fetch” followed by “git merge”,
 so in this case, I’m being more explicit about what I merge with
  39. 45.

    OTHER GIT HOSTING ➤ GitHub is not the only website

    you can use to host repos ➤ GitLab, BitBucket: free private repos ➤ GitLab is open source: can run it on your own server ➤ It’s all Git, so you can clone from GitHub and push to GitLab (or vice versa)
  40. 47.

    RUNNING INTO PROBLEMS, PART 2 ➤ Let’s say you want

    to propose two separate changes, unrelated to each other. One is adding a new recipe, one is modifying an existing recipe. ➤ Try making two separate pull requests. ➤ Spoiler alert: you can’t make more than one pull request between the same two repos, based on what we know so far. Fortunately, we’re not done learning yet!
  41. 48.

    STRUCTURE OF A COMMIT Content +S’mores Recipe + +Ingredients: smores.txt

    Metadata Initial commit Commit Message David Baumgold <david@davidbaumgold.com> Author Sat May 28 10:05:03 2016 Date Commit +This repo contains +recipes from my +personal cookbook. README.txt
  42. 49.

    STRUCTURE OF A COMMIT Content +Salad Recipe + +Ingredients: salad.txt

    Metadata Added a salad recipe Commit Message David Baumgold <david@davidbaumgold.com> Author Sat May 28 10:08:42 2016 Date Commit Content +S’mores Recipe + +Ingredients: smores.txt Metadata Initial commit Commit Message David Baumgold <david@davidbaumgold.com> Author Sat May 28 10:05:03 2016 Date Commit +This repo contains +recipes from my +personal cookbook. README.txt parent pointer
  43. 56.

    MANAGING BRANCHES $ git branch ➤ git branch shows which

    branches exist in the repo,
 and which one you’re currently attached to (if any) ➤ git branch <branchname> creates a new branch pointing
 to the commit you’re currently sitting on ➤ git branch -d <branchname> deletes an existing
 branch from your local repo (not but from remotes!)
  44. 57.

    SHORTCUT $ git checkout -b <branchname> ➤ Creates a new

    branch and immediately switches over to it ➤ This is what you want most of the time!
  45. 58.

    UPSTREAM $ git branch --set-upstream ➤ Every branch has its

    own “upstream” setting:
 the remote that the branch normally pulls from and pushes to,
 and the branch in that remote that it uses for those operations ➤ Normally the branch in the remote has the same name as the
 local branch, but it doesn’t have to!
  46. 60.

    EXERCISE: ADD MORE CHOCOLATE! ➤ On your clone of the

    tutorial-cookbook repo, make a new
 branch called add-chocolate ➤ Check git log to be sure that the commits are the same ➤ Modify a recipe to add chocolate to it (or add more chocolate!) ➤ Commit your modification, and make sure the commit is in
 the add-chocolate branch and not the master branch ➤ Push your branch to GitHub, and make a pull request
 from your add-chocolate branch to my master branch
  47. 61.

    MOVING COMMITS $ git cherry-pick <ref> ➤ git cherry-pick creates

    a new commit that is a copy of
 an existing commit that you reference: same changes,
 same files, same author ➤ You can use a hash, branch name, or any other valid
 Git reference ➤ This does not delete the referenced commit!
  48. 64.

    MOVING BRANCH POINTERS $ git reset <commit> ➤ git reset

    moves the branch pointer to make it point
 to whatever commit you want ➤ By default, does not modify the files in your working
 tree, but use --hard to modify them
  49. 65.

    RELATIVE REFERENCES ➤ Use ~ after a reference to refer

    to its parent commit ➤ You can use multiple tildes (~~~~~) or define a number (~5) ➤ You can use HEAD to refer to the current commit ➤ To refer to the parent of the current commit: HEAD~ To remove the most recent commit from the current branch: $ git reset --hard HEAD~
  50. 67.

    FLASHBACK: DETACHED HEAD ➤ Now we know enough to understand

    Git’s “detached HEAD” warning! ➤ “HEAD” means the current commit ➤ “detached” means not attached to a branch ➤ New commits will also not be attached to a branch! ➤ Hard to find those commits again ➤ Solution: git checkout -b <branchname> to create a new branch for your commits!
  51. 68.

    CONFLICTS ➤ What if you try to cherry-pick a change

    that has already happened on your branch? Or a change in a file that doesn’t exist on your branch? $ git cherry-pick e98d69f0a5942704076182139acb50856ca8bc7c error: could not apply e98d69f... Conflicting commit message hint: after resolving the conflicts, mark the corrected paths hint: with 'git add <paths>' or 'git rm <paths>' hint: and commit the result with 'git commit'
  52. 69.

    RESOLVING CONFLICTS ➤ Git will alter the file to show

    conflicting lines ➤ Edit the file to look the way you want, then use git add to indicate that the conflict is resolved not in conflict <<<<<<< HEAD first part of conflict ======= second part of conflict >>>>>>> Conflicting commit message
  53. 70.

    GIT REBASE $ git rebase <ref> ➤ git rebase does

    a series of cherry-picks to recreate a branch
 on a different commit base, and moves the branch pointer
 to point to the newly-created branch ➤ Just like with cherry-pick, the old commits are not deleted ➤ Rebase is the command for changing history
  54. 71.

    GIT REBASE most recent commits oldest commits c b a

    master d e fix-typos f e′ f′
  55. 72.

    CHANGING HISTORY ➤ Changing history is confusing for others ➤

    Never change history when other people might be using your branch, unless they know you’re doing so ➤ Never change history on master ➤ Best practice: only change history for commits that haven’t yet been pushed to any remote
  56. 73.

    FORCE PUSH c b a master d fix-typos e′ f′

    c b a master d e fix-typos f Local Repo Remote Repo
  57. 74.

    INTERACTIVE REBASE ➤ Step through commits and perform operations on

    them: ➤ Squash multiple commits together ➤ Edit a commit to separate it into multiple smaller ones ➤ Insert, delete, and reorder commits in history ➤ With great power comes great responsibility $ git rebase -i
  58. 75.

    GIT REFLOG $ git reflog ➤ git reflog shows every

    commit you’ve touched recently,
 regardless of where that commit is in Git’s history ➤ Useful for recovering commits that you’ve lost track of ➤ Example: commits you’ve deleted through interactive rebase pronounced “ref-log”, not “re-flog”
  59. 76.

    COMMANDS FOR MOVING COMMITS AROUND ➤ git branch ➤ git

    reset ➤ git cherry-pick ➤ git rebase
  60. 77.

    ALL THE GIT COMMANDS WE KNOW SO FAR git clone

    git remote git push git pull git fetch git merge git log git show git diff git checkout git init git config git status git add git rm git commit making commits viewing commits collaborating git branch git reset git cherry-pick git rebase moving commits
  61. 79.

    GIT TAG ➤ git tag is like git branch, but

    branches move and tags don’t ➤ Useful for historical references: version 1.0 that shipped to customers, or was put on the production website ➤ Tags can be lightweight or annotated $ git tag
  62. 80.

    GIT BLAME ➤ For every line, git blame will tell

    you who last changed the line ➤ Useful for when something broke and you need to know who can fix it ➤ To find out who was the second-to-last to change a line (or further back), check out the commit before when that line changed, and run git blame again $ git blame <file>
  63. 81.

    GIT BISECT ➤ git bisect will help you find which

    commit introduced a breakage or a bug ➤ Provide three things: a working commit, a broken commit, and a test to determine whether a commit is working or not ➤ bisect uses binary search to quickly find the commit where things went from working to broken $ git bisect
  64. 82.

    GIT BISECT $ git bisect start $ git checkout broken-commit

    $ git bisect bad $ git checkout working-commit $ git bisect good
  65. 86.

    GIT BISECT ➤ Even faster with an automated test ➤

    Return code 0 on success, return code 1 on failure $ git bisect run my_test.sh
  66. 87.

    HOOK SCRIPTS ➤ Every Git repo has a “hooks” directory

    in the “.git” directory,
 with scripts that Git will run automatically ➤ Names include: pre-commit, pre-push, pre-rebase, prepare-commit-message, etc ➤ See also: pre-commit.com $ ls .git/hooks
  67. 88.

    GIT ADD BY PATCH ➤ Situation: you’re trying to add

    a new feature, but you discover you need to fix a bug to do so ➤ Should be two separate commits, but code is tangled up ➤ Use git add -p to craft commits one patch at a time, instead of by whole files $ git add -p .
  68. 89.

    CHECK OUT GITHUB PULL REQUESTS Edit your .git/config and add

    this to your GitHub remote: fetch = +refs/pull/*/head:refs/remotes/origin/pr/* Now you can run: git checkout pr/123 And you’ll check out pull request #123 locally! Easy!
  69. 90.

    TEACH GIT ABOUT GITHUB git create — create a GitHub

    repo for your local repo Adds Git commands like: git pull-request — make a pull request git issue create — make a GitHub issue https://hub.github.com/