Difference between revisions of "DPS909 & OSD600 Winter 2017 - Git Walkthrough 2"

From CDOT Wiki
Jump to: navigation, search
(Step 3: Cloning a Forked Repository)
(Step 3: Cloning a Forked Repository)
Line 67: Line 67:
 
# checked-out the latest version of the code to our <code>./Spoon-Knife/</code> working directory
 
# checked-out the latest version of the code to our <code>./Spoon-Knife/</code> working directory
  
 +
Let's take a look at what we have in our new cloned repo:
 +
 +
<pre>
 +
$ cd Spoon-Knife
 +
$ ls
 +
README.md  index.html styles.css
 +
$ git show
 +
commit d0dd1f61b33d64e29d8bc1372a94ef6a2fee76a9
 +
Author: The Octocat <octocat@nowhere.com>
 +
Date:  Wed Feb 12 15:20:44 2014 -0800
 +
 +
    Pointing to the guide for forking
 +
 +
diff --git a/README.md b/README.md
 +
index 0350da3..f479026 100644
 +
--- a/README.md
 +
+++ b/README.md
 +
@@ -6,4 +6,4 @@ Creating a *fork* is producing a personal copy of someone else's project. Forks
 +
 +
After forking this repository, you can make some changes to the project, and submit [a Pull Request](https://github.com/octocat/Spoon-Knife/pulls) as practice.
 +
 +
-For some more information on how to fork a repository, [check out our guide, "Fork a Repo"](https://help.github.com/articles/fork-a-repo). Thanks! :sparkling_heart:
 +
+For some more information on how to fork a repository, [check out our guide, "Forking Projects""](http://guides.github.com/overviews/forking/). Thanks! :sparkling_heart:
 +
</pre>
 +
 +
===Step 4: Syncing Changes Between Repositories===
 +
 +
Let's make a change to our cloned Spoon-Knife repo, then sync that change with our remote Github forked repository.  We start by making a change locally.
 +
 +
In your editor, open the <code>Spoon-Knife/index.html</code> file and make a change to the text, for example:
 +
 +
{| class="wikitable"
 +
! style="font-weight: bold;" | Before
 +
! style="font-weight: bold;" | After
 +
|-
 +
| <pre>
 +
<!-- Feel free to change this text here -->
 +
<p>
 +
  Fork me? Fork you, @octocat!
 +
</p>
 +
</pre>
 +
| <pre>
 +
<p>
 +
  Look, Mom, I'm on Github!
 +
</p>
 +
</pre>
 +
|}
 +
 +
Now we can '''add''' and '''commit''' our change:
 +
 +
<pre>
 +
$ git status
 +
On branch master
 +
Your branch is up-to-date with 'origin/master'.
 +
Changes not staged for commit:
 +
  (use "git add <file>..." to update what will be committed)
 +
  (use "git checkout -- <file>..." to discard changes in working directory)
 +
 +
modified:  index.html
 +
 +
no changes added to commit (use "git add" and/or "git commit -a")
 +
$ git add index.html
 +
$ git commit -m "Update text in index.html"
 +
[master 57f7209] Update text in index.html
 +
1 file changed, 1 insertion(+), 2 deletions(-)
 +
$ git show
 +
commit 57f7209f758c4ba32be537434196b9168b2d53dc
 +
Author: David Humphrey (:humph) david.humphrey@senecacollege.ca <david.humphrey@senecacollege.ca>
 +
Date:  Thu Jan 12 11:48:56 2017 -0500
 +
 +
    Update text in index.html
 +
 +
diff --git a/index.html b/index.html
 +
index a83618b..e4cff78 100644
 +
--- a/index.html
 +
+++ b/index.html
 +
@@ -11,9 +11,8 @@
 +
 +
<img src="forkit.gif" id="octocat" alt="" />
 +
 +
-<!-- Feel free to change this text here -->
 +
<p>
 +
-  Fork me? Fork you, @octocat!
 +
+  Look, Mom, I'm on Github!
 +
</p>
 +
 +
</body>
 +
</pre>
 +
 +
Before our commit, there were 3 commits in the repo's log.  Now there are 4:
 +
 +
<pre>
 +
$ git log
 +
commit 57f7209f758c4ba32be537434196b9168b2d53dc
 +
Author: David Humphrey (:humph) david.humphrey@senecacollege.ca <david.humphrey@senecacollege.ca>
 +
Date:  Thu Jan 12 11:48:56 2017 -0500
 +
 +
    Update text in index.html
 +
 +
commit d0dd1f61b33d64e29d8bc1372a94ef6a2fee76a9
 +
Author: The Octocat <octocat@nowhere.com>
 +
Date:  Wed Feb 12 15:20:44 2014 -0800
 +
 +
    Pointing to the guide for forking
 +
 +
commit bb4cc8d3b2e14b3af5df699876dd4ff3acd00b7f
 +
Author: The Octocat <octocat@nowhere.com>
 +
Date:  Tue Feb 4 14:38:36 2014 -0800
 +
 +
    Create styles.css and updated README
 +
 +
commit a30c19e3f13765a3b48829788bc1cb8b4e95cee4
 +
Author: The Octocat <octocat@nowhere.com>
 +
Date:  Tue Feb 4 14:38:24 2014 -0800
 +
 +
    Created index page for future collaborative edits
 +
</pre>
 +
 +
Our local repo and our forked repo on Github are not out of sync: our local repo is '''ahead''' of the remote fork by '''1 commit'''.  By default, repos don't stay in sync.  You can do whatever you want locally, and only share commits between repos when you want/need to do so.
 +
 +
Let's send our local changes (i.e., the new commit) to the remote forked repo.  We do this using git's <code>push</code> command.  Before we use <code>push</code>, we need to mention another git command, <code>remote</code>.
 +
 +
We said above that git repos aren't automatically kept in sync with one another, which is true.  However, a git repo can be made aware of remote repos (i.e., other copies of the same repo that you or someone else owns) that you care about.  For example, you might be working on a team of 3 developers, and want to tell git about each of their forks on Github, as well as your own.  This lets you share commits between various remote repos.
 +
 +
When you clone a repo, git automatically sets up remote for you called <code>origin</code>.  You can see it by doing this:
 +
 +
<pre>
 +
$ git remote -v
 +
origin git@github.com:humphd/Spoon-Knife.git (fetch)
 +
origin git@github.com:humphd/Spoon-Knife.git (push)
 +
</pre>
 +
 +
Here git shows two remote URLs, one for '''fetch''' and one for '''push'''.  By default they are the same, although it's possible [http://sleepycoders.blogspot.ca/2012/05/different-git-push-pullfetch-urls.html to have different URLs for the same remote].  We can also add more remotes by giving a '''remote name''' and a '''git URL''', like so:
 +
 +
<pre>
 +
$ git remote add upstream https://github.com/octocat/Spoon-Knife.git
 +
$ git remote -v
 +
origin git@github.com:humphd/Spoon-Knife.git (fetch)
 +
origin git@github.com:humphd/Spoon-Knife.git (push)
 +
upstream https://github.com/octocat/Spoon-Knife.git (fetch)
 +
upstream https://github.com/octocat/Spoon-Knife.git (push)
 +
</pre>
 +
 +
Now we have 2 remotes:
 +
 +
* <code>origin</code> - our personal forked copy on Github
 +
* <code>upstream</code> - the so-called ''upstream'' version of the repo, the one we originally forked
 +
 +
This is a very common way to set up your remotes.  You can obviously use any names you like vs. <code>origin</code> and <code>upstream</code> (you can also use <code>git remote rename</code> if you want to change the names later).
 +
 +
With our remotes set up, we're ready to '''push''' our local change (commit) to our forked repo on Github:
 +
 +
<pre>
 +
$ git push origin
 +
Counting objects: 3, done.
 +
Delta compression using up to 8 threads.
 +
Compressing objects: 100% (3/3), done.
 +
Writing objects: 100% (3/3), 423 bytes | 0 bytes/s, done.
 +
Total 3 (delta 1), reused 0 (delta 0)
 +
remote: Resolving deltas: 100% (1/1), completed with 1 local objects.
 +
To github.com:humphd/Spoon-Knife.git
 +
  d0dd1f6..57f7209  master -> master
 +
</pre>
 +
 +
If everything goes according to plan, you should be able to see your commit on Github.  For me, it's visible via the following URL:
 +
 +
https://github.com/humphd/Spoon-Knife/commits/master
 +
 +
Change it to use your username, and make sure you see your changes:
 +
 +
https://github.com/{your-username}/Spoon-Knife/commits/master
 +
 +
My full commit is visible at https://github.com/humphd/Spoon-Knife/commit/57f7209f758c4ba32be537434196b9168b2d53dc
  
* Client Server (SVN) and Distributed (Git)
 
* Snapshots vs. versioned files.
 
** Walkthrough -
 
** Checksums, SHA-1 ([http://www.miraclesalad.com/webtools/sha1.php try online])
 
** Starting a Git Repo:
 
*** git init
 
*** git clone
 
** File States:
 
*** Untracked (not known to git)
 
*** Tracked: modified, staged, committed
 
** The staging area
 
* Basic Git Commands and Concepts
 
** git help ''<command>''
 
** git add
 
** git commit, git commit -m, git commit -a
 
** git rm
 
** git mv
 
** git status
 
** git log
 
** git diff, git diff --staged
 
** .gitignore
 
** Branches
 
*** HEAD, master
 
*** git checkout, git checkout -b
 
*** git branch, git branch -a, git branch -d, git branch --merged, git branch --contains
 
*** git merge
 
*** git rebase
 
 
** Remotes
 
** Remotes
 
*** origin, origin/''branch''
 
*** origin, origin/''branch''
Line 103: Line 249:
 
*** git push
 
*** git push
 
** Github, Pull Requests
 
** Github, Pull Requests
 +
 +
** .gitignore
 +
** Branches
 +
*** HEAD, master
 +
*** git checkout, git checkout -b
 +
*** git branch, git branch -a, git branch -d, git branch --merged, git branch --contains
 +
*** git merge
 +
*** git rebase

Revision as of 13:09, 12 January 2017

Git Walkthrough: Working Remote

In the previous walk-through, we looked at the basics of using git for revision control. This time we we'll learn how to use git in a distributed workflow, and how to interact with remote repositories, such as those on Github.

Step 1: Using Git with Github

For this walkthrough, we'll need an account on Github. Think of a Github account like a driver's license: it's what allows you to participate in many open source projects. If you haven't done so before, take a few minutes to do the following:

  1. create an account
  2. verify your email address
  3. consider enabling two-factor authentication
  4. add info to your account bio
  5. consider changing your profile picture

We'll also need to do a bit more setup with git. Specifically, we need to set some global config options, SSH keys, etc:

  1. set your username locally
  2. set your email address locally
  3. set your line endings
  4. consider setting other global defaults while you're at it (e.g., your default editor)
  5. set up SSH keys

Step 2: Clones and Forking

Git is a distributed revision control system, which means that unlike client/server systems, git has no concept of a central server that we work against. Instead, everyone who works on a repository first creates his or her own copy. If I want to work with a repository that you made, my first task is to make my own personal copy, then work on that directly.

Git calls this copy of a repository a clone. One of the great advantages of having your own local clone of a repository is that you don't need a network connection in order to work with it (i.e., everything is local), and you have complete control over everything you do (i.e., you don't need permission to commit changes). Cloning a repository copies every commit and version of every file in the original project's history. As a result, git clones can take a lot of disk space.

Every git developer works directly with his or her own local clone of a repository, then uses a combination of git's push and pull commands to sync their work with remote repositories--we'll do this below. Because its so common to want to share our local repositories with one another, and to clone each other's repositories locally, we use Github as a public host.

It's possible with git to clone repositories from a USB key, or copy entire repos across a shared drive. But it's not realistic to do this with people on the other side of the world. Instead, it's more convenient to use the Internet and a shared hosting platform.

Every Github user can have an unlimited number of open source repositories (private/closed source repositories cost money). Because the default workflow with git is to clone a repository before we use it, Github includes this as a central feature, which it calls forking.

What Github calls a fork is really just another name for a clone. You'll see both fork and clone used on Github, and you can think of the difference this way:

  • fork: copy an existing Github repository to your Github account. This forked copy will live on Github's servers, but you will have full ownership over it. It's typical to fork any repository to which you want to contribute.
  • clone: create a local copy of a repository on Github on your computer. It's typical to clone repositories that you have previously forked.

Let's fork a repository. Follow the instructions in Fork a Repo to fork the Spoon-Knife repository.

While we're at it, let's also fork the Bootstrap repository, so we can carry on with things we were trying in our earlier walkthrough.

Step 3: Cloning a Forked Repository

Now that we have a forked copy of the Spoon-Knife repository, let's clone it to our local computer. In order to clone a Github repository, we need an appropriate URL. NOTE: this is not the URL we use to access the repository in our web browser. Rather, we need a git URL.

Github provides git URLs using various protocols. The one we'll use most often is the SSH URL. To get an SSH URL for a Github repository, you need to have the appropriate rights (i.e., both read and write permissions). Every repository that you fork will automatically have these rights.

In my case, the URL I need is git@github.com:humphd/Spoon-Knife.git, and for you it will be git@github.com:{your-github-username}/Spoon-Knife.git. Using this SSH URL we can clone the repo locally:

$ git clone git@github.com:humphd/Spoon-Knife.git
Cloning into 'Spoon-Knife'...
remote: Counting objects: 16, done.
remote: Total 16 (delta 0), reused 0 (delta 0), pack-reused 16
Receiving objects: 100% (16/16), done.
Resolving deltas: 100% (3/3), done.

This did a few things:

  1. created a directory ./Spoon-Knife/
  2. created a .git/ database folder in ./Spoon-Knife/.git
  3. downloaded all commits in the forked repo from Github, saving them to our ./Spoon-Knife/.git database
  4. created remote tracking for the origin repository (i.e., our forked repo on Github, from which we cloned)
  5. checked-out the latest version of the code to our ./Spoon-Knife/ working directory

Let's take a look at what we have in our new cloned repo:

$ cd Spoon-Knife
$ ls
README.md  index.html styles.css
$ git show
commit d0dd1f61b33d64e29d8bc1372a94ef6a2fee76a9
Author: The Octocat <octocat@nowhere.com>
Date:   Wed Feb 12 15:20:44 2014 -0800

    Pointing to the guide for forking

diff --git a/README.md b/README.md
index 0350da3..f479026 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,4 @@ Creating a *fork* is producing a personal copy of someone else's project. Forks

 After forking this repository, you can make some changes to the project, and submit [a Pull Request](https://github.com/octocat/Spoon-Knife/pulls) as practice.

-For some more information on how to fork a repository, [check out our guide, "Fork a Repo"](https://help.github.com/articles/fork-a-repo). Thanks! :sparkling_heart:
+For some more information on how to fork a repository, [check out our guide, "Forking Projects""](http://guides.github.com/overviews/forking/). Thanks! :sparkling_heart:

Step 4: Syncing Changes Between Repositories

Let's make a change to our cloned Spoon-Knife repo, then sync that change with our remote Github forked repository. We start by making a change locally.

In your editor, open the Spoon-Knife/index.html file and make a change to the text, for example:

Before After
<!-- Feel free to change this text here -->
<p>
  Fork me? Fork you, @octocat!
</p>
<p>
  Look, Mom, I'm on Github!
</p>

Now we can add and commit our change:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
$ git add index.html
$ git commit -m "Update text in index.html"
[master 57f7209] Update text in index.html
 1 file changed, 1 insertion(+), 2 deletions(-)
$ git show
commit 57f7209f758c4ba32be537434196b9168b2d53dc
Author: David Humphrey (:humph) david.humphrey@senecacollege.ca <david.humphrey@senecacollege.ca>
Date:   Thu Jan 12 11:48:56 2017 -0500

    Update text in index.html

diff --git a/index.html b/index.html
index a83618b..e4cff78 100644
--- a/index.html
+++ b/index.html
@@ -11,9 +11,8 @@

 <img src="forkit.gif" id="octocat" alt="" />

-<!-- Feel free to change this text here -->
 <p>
-  Fork me? Fork you, @octocat!
+  Look, Mom, I'm on Github!
 </p>

 </body>

Before our commit, there were 3 commits in the repo's log. Now there are 4:

$ git log
commit 57f7209f758c4ba32be537434196b9168b2d53dc
Author: David Humphrey (:humph) david.humphrey@senecacollege.ca <david.humphrey@senecacollege.ca>
Date:   Thu Jan 12 11:48:56 2017 -0500

    Update text in index.html

commit d0dd1f61b33d64e29d8bc1372a94ef6a2fee76a9
Author: The Octocat <octocat@nowhere.com>
Date:   Wed Feb 12 15:20:44 2014 -0800

    Pointing to the guide for forking

commit bb4cc8d3b2e14b3af5df699876dd4ff3acd00b7f
Author: The Octocat <octocat@nowhere.com>
Date:   Tue Feb 4 14:38:36 2014 -0800

    Create styles.css and updated README

commit a30c19e3f13765a3b48829788bc1cb8b4e95cee4
Author: The Octocat <octocat@nowhere.com>
Date:   Tue Feb 4 14:38:24 2014 -0800

    Created index page for future collaborative edits

Our local repo and our forked repo on Github are not out of sync: our local repo is ahead of the remote fork by 1 commit. By default, repos don't stay in sync. You can do whatever you want locally, and only share commits between repos when you want/need to do so.

Let's send our local changes (i.e., the new commit) to the remote forked repo. We do this using git's push command. Before we use push, we need to mention another git command, remote.

We said above that git repos aren't automatically kept in sync with one another, which is true. However, a git repo can be made aware of remote repos (i.e., other copies of the same repo that you or someone else owns) that you care about. For example, you might be working on a team of 3 developers, and want to tell git about each of their forks on Github, as well as your own. This lets you share commits between various remote repos.

When you clone a repo, git automatically sets up remote for you called origin. You can see it by doing this:

$ git remote -v
origin	git@github.com:humphd/Spoon-Knife.git (fetch)
origin	git@github.com:humphd/Spoon-Knife.git (push)

Here git shows two remote URLs, one for fetch and one for push. By default they are the same, although it's possible to have different URLs for the same remote. We can also add more remotes by giving a remote name and a git URL, like so:

$ git remote add upstream https://github.com/octocat/Spoon-Knife.git
$ git remote -v
origin	git@github.com:humphd/Spoon-Knife.git (fetch)
origin	git@github.com:humphd/Spoon-Knife.git (push)
upstream	https://github.com/octocat/Spoon-Knife.git (fetch)
upstream	https://github.com/octocat/Spoon-Knife.git (push)

Now we have 2 remotes:

  • origin - our personal forked copy on Github
  • upstream - the so-called upstream version of the repo, the one we originally forked

This is a very common way to set up your remotes. You can obviously use any names you like vs. origin and upstream (you can also use git remote rename if you want to change the names later).

With our remotes set up, we're ready to push our local change (commit) to our forked repo on Github:

$ git push origin
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 423 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local objects.
To github.com:humphd/Spoon-Knife.git
   d0dd1f6..57f7209  master -> master

If everything goes according to plan, you should be able to see your commit on Github. For me, it's visible via the following URL:

https://github.com/humphd/Spoon-Knife/commits/master

Change it to use your username, and make sure you see your changes:

https://github.com/{your-username}/Spoon-Knife/commits/master

My full commit is visible at https://github.com/humphd/Spoon-Knife/commit/57f7209f758c4ba32be537434196b9168b2d53dc

    • Remotes
      • origin, origin/branch
      • git remote
      • git remote add
      • git fetch
      • git pull
      • git push
    • Github, Pull Requests
    • .gitignore
    • Branches
      • HEAD, master
      • git checkout, git checkout -b
      • git branch, git branch -a, git branch -d, git branch --merged, git branch --contains
      • git merge
      • git rebase