After reading this you should understand the git repository model.
Also you should be able to init, clone, push, pull, fetch, merge, checkout,
and commit
documents.
To start a new project with git you can use either init
.
If you want to create a new project, then create a new folder,
or go into an existing folder that you want to turn into a git repository.
From inside that folder, run the command
git init
This creates a new git repository!
Note that unlike other version control systems such as SVN, the repo is living in your folder.
In fact there is a .git
directory, if you run ls -a
you can see it
(directories beginning with a dot are usually not reported by the ls
command).
In fact you can run the command ls .git
and see that there are some folders in this directory.
It is not important what these folders do, what is important is realizing that the whole repository is stored in this .git
folder.
What is not the repository is whatever files or folders that appear when you type ls
.
Nor is it located on some server, or even somewhere else on this server.
Perhaps you want to collaborate with somebody, or just want a copy of somebody else's work.
If they are storing their work in a git repository, you can clone that repository to get a copy of it.
Let say there are some design specs that you need in /home/lcalrissian/falcon
on your local computer, and you want to create your copy.
To create a copy into your home directory, you can run
git clone /home/lcalrissian/falcon
this creates a new folder falcon
in the directory you ran the command from.
Alternatively, if this is stored on another server, say docs.cloudcity.com
you can run the command,
git clone git@docs.cloudcity.com:falcon
Note : the command differs by server and setup, read the server's or project's documentation to clone the repository.
Once again, this creates a repository in falcon/.git
.
Adding data to the repository requires two steps, first you have to stage your changes.
Then you commit staged changes to the repository.
If you have a file jabba/debts.txt
, you can stage that file as
git add jabba/debts.txt
You can check the current state of the repository at any time with
git status
and the new data that is added with
git diff --staged
Commit the changes with
git commit
or unstage the changes by using
git reset -- .
or just that particular file
git reset -- jabba/debts.txt
Git doesn't differentiate new files or changes to files. Git doesn't keep track of files, instead it keeps track of the contents of the files. Therefore modifying the data requires the same steps as adding a new file.
To tell git to remove a file is just as easy.
If you no longer need a file, just say, jabba/debts.txt
run
git rm jabba/debts.txt
to commit the changes you can run
git commit
If it turns out you need an older version of a file, you can always check it out again.
For instance if you need to get the file jabba/debts.txt
back, you can run
git checkout HEAD~1 jabba/debts.txt
this checks out the jabba/debts.txt
from the repository into your working directory.
The HEAD~1
is shorthand for the previous commit, (HEAD~2
would be two commits ago).
If you made some changes to a file, but don't like them, you can just run
git checkout jabba/debts.txt
which will get you a fresh copy of what you started with.
Alternatively you can look up the commit name, and reference that instead.
Since you probably don't remember commit names, you can run
git log
to look at the commit log, then run
git checkout 1337 jabba/debts.txt
assuming 1337
is a commit hash (or a unique beginning of one).
If you know that you will be using a commit in the future you can tag it, for instance
git tag -l 'ep_IV'
and then instead of using the hash, you can just use the tag name,
git checkout ep_IV jabba/debts.txt
Sometimes you will want to make changes to the repository and keep a clean version around as well. You can use branches to do so. For instance if you want to modify the hyperdrive, but want to have a working copy at all times, you can run
git branch hyperdrive
at any time you can switch to that branch by using
git checkout hyperdrive
and view a list of all branches with
git branch
(Note : the default branch is master
).
If you run into a bug while developing a branch, but it applies to more than just that branch then you should only apply the change once.
Make the change on the root branch, say master
and commit it, then propagate the change by merging it with every other branch.
Checkout a branch the fix applies to, say hyperdrive
and run the command,
git merge master
It makes sense to keep around common ancestors of multiple branches for just this purpose.
This helps git keep track of which changes represent what so that it recognizes one single bug fix, instead of two different ones.
Just as you can checkout files from commits, you can also checkout files from other branches. However odds are you really want to merge, as that keeps commit history. If you ever find yourself copying a file between branches, you should stop and think whether you could have modified the file at a common ancestor and merged changes into both branches.
While git is useful as a version control tool, it is structured such that it can be a very powerful collaboration tool. By keeping track of modifications as opposed to files, git allows many users to easily modify the contents of a large project.
Just like tags allow you to rename commits from inconvient SHA hashes to nice names, git allows you to rename long locations of repositories to shorter remote names. For the rest of this section we will be using the short remote names, but you could use a full path to a repository instead. To set up a remote, you can run the command
git remote add rebels git@rebels.yavin4.gov:falcon
This means when you reference rebels
you will really be referencing git@rebels.yavin4.gov:falcon
.
By default origin
refers to whatever repository you cloned.
(Note : remote names are not shared between repositories)
Sometimes your collaborators will make changes to their repository that you may want.
If that is the case, you can fetch those changes using the git fetch
command.
git fetch rebels
fetches all of the changes made in the rebels
repository.
The command will print out a list of all the branches in that repository.
To merge branch rebel-hyperdrive
with your local branch hyperdrive
, make your current branch hyperdrive
and run
git merge rebels/rebel-hyperdrive
You can compress those two steps into one by running
git pull rebels rebel-hyperdrive:hyperdrive
Some repositories are only used for distributing documents, and nobody is using them locally.
If for instance the rebels also keep a github
account for keeping the latest and greatest falcon documentation, you may wish to push to there.
Pushing your dev
branch to the remote hyperdrive
branch requires the command,
git push github dev:hyperdrive
(Note: the branch ordering is reversed from the pull command)
A few comments on the previous command, first the command assumed that github
was a valid remote.
Second, the hyperdrive
branch must not exist, or you must have in dev
's history the latest commit to that branch.
Otherwise you will have to merge in those changes by using the instructions in the fetching changes section.
Finally, the remote must be a bare repository, bare repositories do not have local commits and can only be used as a common distribution point.