What Does Cloning a Github Repository Mean

What does cloning a GitHub repository mean?

To clone a repository means to duplicate and download everything in the repository.

You are on a Mac, so launch Terminal, create a folder and type this command:

git clone git://github.com/facebook/facebook-ios-sdk.git

It will duplicate and download the entire repository.

What's the difference between cloning and copying a git repo?

Cloning a repository gives you a copy of that repository and configures the original repository as a remote.

Copying a repository just gives you a copy of that repository. (Though you can of course just add the remote definition afterwards via git remote add.)


Copying a repository copies its .git/config file, and thus its remotes. Cloning a repository does not copy the config file, and thus the remotes are not shared. (The repository that was cloned from is set as the origin remote in the resulting clone.)

What is the difference between pull and clone in git?

They're basically the same, except clone will setup additional remote tracking branches, not just master. Check out the man page:

Clones a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository (visible using git branch -r), and creates and checks out an initial branch that is forked from the cloned repository's currently active branch.

What is the difference between Forking and Cloning on GitHub?

Basically, yes. A fork is just a request for GitHub to clone the project and registers it under your username; GitHub also keeps track of the relationship between the two repositories, so you can visualize the commits and pulls between the two projects (and other forks).

You can still request that people pull from your cloned repository, even if you don't use fork -- but you'd have to deal with making it publicly available yourself. Or send the developers patches (see git format-patch) that they can apply to their trees.

Difference between cloning and downloading

When you download the repo it just gives you all the source files with no .git so you dont have the repo. When you clone you get a copy of the history and it is a functional git repo.

Cloning a repo from someone else's Github and pushing it to a repo on my Github

As Deefour says, your situation isn't much unlike the one in Change the URI (URL) for a remote Git repository. When you clone a repository, it is added as a remote of yours, under the name origin. What you need to do now (as you're not using the old source anymore) is change origin's URL:

$ git remote set-url origin http://github.com/YOU/YOUR_REPO

If the original repository would update often and you want to get those updates from time to time, then instead of editing origin it would be best to add a new remote:

$ git remote add personal http://github.com/YOU/YOUR_REPO

Or maybe even call the old one upstream:

$ git remote rename origin upstream
$ git remote add origin http://github.com/YOU/YOUR_REPO

Then, whenever you want to get changes from upstream, you can do:

$ git fetch upstream

As this the source is a sample repository (seems to be kind of a template to start off), I don't think there's a need to keep it nor fork it at all - I'll go with the first alternative here.

As a beginner, is cloning a local repo a good way to dev and deploy code on the same box? How?

Yes, and it's easy.

Yes for the reasons you stated: you're learning git. Cloning locally works identically to cloning a remote repo on GitHub or wherever, the only difference is that instead of a GitHub URL or SSH path, you use a directory path. In fact, when you clone a local repo, that existing repo will be considered a remote of the new one. And unlike a GitHub repo, you can manage both repos using the git CLI.

You can even make the new repo a remote of the original, pushing or pulling changes from either end. But if you're using this to get used to working with a GitHub repo, keep the relationship one-way, and do your development on the repo that is downstream, which is the one that you create as a clone of the one that is upstream, also the origin in this case. Have Task Scheduler execute from the upstream repo's worktree.

You want to have your setup end up looking like this:

origin/upstream:       path/to/origin/script.py
README.md
.git

clone/downstream: path/to/clone/script.py
README.md
.git

Try not to get confused by all the terms, they are just naming conventions. The path/to/origin/ repo will variously be called an upstream, the origin, a remote of the path/to/clone/ repo. And no, the directories, of the repos do not have to be named "origin" or "clone" -- the paths and files above are just examples.

steps

  1. Move your existing repo to where you want to run your scheduled task from. If it's already there, great.

  2. On your command line, cd to the directory within which you want the new clone directory to go.

  3. Execute the following:

    git clone path/to/origin

    using the actual path to wherever you put it in step 1.

    This mimics the git clone github.com/path/to/origin command you'd use to clone a GitHub repo.

    It will create a new directory in the current directory with the same name as the directory you are cloning. If for some reason you need it to have a differnent name, e.g. if the origin and the clone are in the same parent directory, use this command instead:

    git clone path/to/origin path/to/clone

    The new directory will contain a git repo (the .git dir) and all the files in the main branch will be checked out.

    If you mess up, no big deal. Delete the newly created directory (not the origin!), and start over.

  4. You can confirm the relationship between the two repos by cd-ing into the clone directory and typing:

    git remote -v

    You will see the remote was given the name "origin" by default. It's just a convention as I said, and you can actually change the name, but as a beginner it's best to stick to the defaults.

  5. To see all the branches in both repos, and to confirm the tracking relationship between the main/master branches on the two repos, type:

    git branch -vva

basic workflow

  • do all your work in the clone repo

  • push new commits, new branches, etc to your remote (aka upstream, origin) repo as you need to, e.g.:

    git push

    You don't need to specify the push destination when you're in a branch that has a remote tracking branch (what you saw in step 5 above).

    This step simply syncs whatever you push into the remote git repo database. It DOES NOT update what is checked out into its worktree. In other words, your scheduled task will keep executing the same version of the code it was running before.

  • To update what your scheduled task executes, cd to that repo and execute a git command to checkout whatever version of the code you want it to execute going forward. If it's just whatever is the latest commit is on the branch it already has checkout out, it's a simple:

    git pull

a bit more advanced

If you want to better mimic setups that rely on central repo server (such as GitHub), you would have three repos related like so:

           origin/upstream
| |
______| |_____
| |
dev clone |
deploy clone <-- your scheduled task runs in this repo

Hope this helps. Let me know if you have any questions.

Clone from a local repository, then pushing back the changes

Git's remote repository can be from ssh, https, and directory.

In your example,

  • /original/.git have remote origin that points to github (either via ssh or https, e.g.: https://github.com/user/example.git)
  • /cloned_one/.git have remote origin that points to directory (e.g.: /original/.git

This looks like some kind of linked list:

[/cloned_one/.git] --origin--> [/original/.git] --origin--> [github]

Here is an example command to reproduce such setup:

$ cd /tmp
$ git clone https://github.com/schacon/example.git original
Cloning into 'original'...
remote: Enumerating objects: 4, done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 4
Receiving objects: 100% (4/4), 18.52 KiB | 3.70 MiB/s, done.
$ mkdir cloned_one
$ git clone /tmp/original cloned_one
Cloning into 'cloned_one'...
done.
$ cd cloned_one/
$ echo newfile > newfile.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Untracked files:
(use "git add <file>..." to include in what will be committed)
newfile.txt

nothing added to commit but untracked files present (use "git add" to track)
$ git add newfile.txt
$ git commit -m 'add new file'
[master e45e780] add new file
1 file changed, 1 insertion(+)
create mode 100644 newfile.txt
$ git remote -v
origin /tmp/original (fetch)
origin /tmp/original (push)
$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)

nothing to commit, working tree clean

Now, the cloned_one is 1 commit ahead of original

You can push changes from cloned_one to original with (remember to cd /tmp/cloned_one first):

  • git push
  • git push origin master
  • git push /tmp/original master

Here, the syntax of pushing is to specify where you want to push (e.g.: to origin, or to /tmp/original directory), and what branch you want to push

$ cd /tmp/cloned_one/
$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)

nothing to commit, working tree clean
$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 333 bytes | 333.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /tmp/original
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to '/tmp/original'

Now it says that you have trouble pushing to /tmp/original because its not a bare repo. You can fix this by either changing /tmp/original to bare repo, or just configure it to update its worktree when being pushed to like below:

$ cd /tmp/original/
$ git config receive.denyCurrentBranch updateInstead
$ cd /tmp/cloned_one/
$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 333 bytes | 333.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To /tmp/original
c3d5e92..e45e780 master -> master

Now, if you want to push your changes back to github (the origin of /tmp/original) you can push it from /tmp/original or from /tmp/cloned_one:

  • cd /tmp/original ; git push origin master
  • cd /tmp/cloned_one ; git push https://github.com/username/example.git

Notice that when pushing from /tmp/original, you can specify the target as origin (since the origin of /tmp/original is from github). While when pushing from /tmp/cloned_one, you have to specify the target as full URL.

You can also change cloned_one's remote to point to github (search for git remote manual)

Further reading:

  • what's a bare repo?
    • Bare repository is just a normal repository, but without the file checked out (e.g.: just the .git directory),
    • What's the -practical- difference between a Bare and non-Bare repository?
    • https://mijingo.com/blog/what-is-a-bare-git-repository
    • the content of a bare repository is the same with .git directory inside a non-bare repo (to convert a non-bare to bare, you just need to git config --bool core.bare true and delete its working directory)
  • about why ! [remote rejected] master -> master (branch is currently checked out) issue happens, you can read:
    • Git Push error: refusing to update checked out branch
    • https://cbx33.github.io/gitt/chap6-5.html


Related Topics



Leave a reply



Submit