**This document is a work in progress.**
Use Piazza to suggest further Git tips and tricks we might include.
In **[working locally](./local.html)**, all the commands we used were only operating _locally_; that is, they haven't gone past your computer.
This is still pretty useful, but sometimes you want to go further.
## Remotes
Unlike other similar systems, Git doesn't have built-in a notion of a "central repository."
Instead, any repository can push to any other repository by specifying it as a "remote."
A "remote" is just a pair of a name (which can be anything) and a URI, which is a string indicating how it can find the other repository. The URI might look something like this:
`ssh://USERNAME@athena.dialup.mit.edu/mit/6.005/git/SEMESTER/psets/PSET/USERNAME.git`
Breaking that down:
* `ssh://` --- this specifies the _protocol_ git should use to transfer the data.
SSH is a protocol that lets you send data securely, which is useful to us because we have to type in a password.
But in principle this is totally analogous to, for example, the `http://` which you see in web browsers (HTTP is a protocol commonly used for data on the Web).
* `USERNAME@athena.dialup.mit.edu` --- this actually has two parts.
The `USERNAME` is the username you use to log in to the server.
The `athena.dialup.mit.edu` is the address of the server itself.
`athena.dialup.mit.edu` is the name of an Athena server IS&T runs.
It accepts Kerberos logins, so your `username` can just be your Kerberos name.
* `/mit/6.005/git/SEMESTER/psets/PSET/USERNAME.git` --- this is the path on the server where the repository is stored.
(Note that you should use the actual path specified in the pset that you're about to work on, so that SEMESTER and PSET are replaced with the right things.)
One noteworthy thing here is the `USERNAME.git` part at the end.
In 6.005, this will always be your username, or the usernames of your group members in a group project.
However, there's nothing in Git to say that the username you log in with (the thing before the `@` sign) and repository name at the end of the path have to match.
In 6.005, we just set it up that way.
Now, even though Git doesn't have the idea of a central repository, it's very useful for 6.005.
Thus, in 6.005, all of your repositories are actually created by _cloning_ a remote repository which we create (and which acts as the "central" repository).
You've done this with the `git clone URI directory` command a bunch of times now.
This actually does a couple of things:
1. Create an empty directory called `directory` (i.e. the last argument to `git clone`).
2. Initialize it as an empty Git repository.
3. Add a remote with the URI you specified and the name `origin`.
4. Download the data from the remote.
So for those of you who were wondering, that's what the `origin` means.
It's just the default name of the remote repository that you cloned your repository from.
## Pushing
After you've made some commits, you might want to push them to a remote repository.
Again, in 6.005, you really only have one remote repository to push to, called `origin`.
To push to it, you run the command:
`git push origin master`
The `origin` in the command specifies that you're pushing to the `origin` remote.
The `master` refers to the `master` branch.
Branches are an advanced feature of Git that we're not going to be using in 6.005, but since Git has them, you do have to specify a branch.
For now, just include this part when you push.
Once you run this, you will be prompted for your password and hopefully everything will push.
You'll get a line like this:
a67cc45..b4db9b0 master -> master
Sometimes, though, things will go wrong. You might get an output like
this:
! [rejected] master -> master (non-fast-forward)
What's going on here is that Git won't let you push to a repository unless all your commits come after all the ones already in your remote repository.
If you get an error message like that, it means that there is a commit in your remote repository that you don't have in your local one (probably because a teammate pushed before you did).
If you find yourself in this situation, you have to pull first and then push.
## Pulling
To perform a pull, you should run `git pull origin` (again, the `origin` tells Git that you're pulling from the `origin` remote).
When you run this, Git actually does two things:
1. It downloads the changes and stores them in its internal state. At this point, your repository doesn't appear any different---it just knows what the state of the remote repository is and what the state of your repository is.
2. It incorporates the changes from the remote repository into the new repository via a process called _merging_.
### Merging
If you made some changes to your repository and you're trying to incorporate the changes from another repository, you need to merge them together somehow.
In terms of commits, what actually needs to happen is that you have to create a special _merge_ commit which encompasses both changes.
How this process actually happens depends on the changes.
If you're lucky, then the changes you made and the changes that you downloaded from the remote repository don't conflict.
For example, maybe you changed one file and your partner changed another.
In this case, it's safe to just include both changes.
Similarly, maybe you changed different functions of the same file.
In these cases, Git can do the merge automatically.
When you run `git pull`, it will pop up an editor as if you were making a commit---in fact, this is the commit message of the merge commit that Git automatically generated.
Once you save and close this editor, the merge commit will be made and you will have incorporated the changes.
At this point, you can try to `git push` again and hopefully it will work this time.
Sometimes, you're not so lucky.
If the changes you made and the changes you pulled edit the same part of the same file, Git won't know how to resolve it.
This is called a _merge conflict_. In this case, you will get an output that says `CONFLICT` in big letters.
If you run `git status`, it will show the conflicting files with the label `Both modified`.
You now have to edit these files and resolve them by hand.
First, open them up in your text editor (probably Eclipse for 6.005).
The parts that are conflicted will be really obviously marked with obnoxious `<<<<<<<<<<<<<<<<<<`, `==================`, and `>>>>>>>>>>>>>>>>>>` lines.
Everything between the `<<<<` and the `====` lines are the changes you made.
Everything between the `====` and the `>>>>` lines are the changes you pulled in.
It's your job to figure out how to combine these.
The answer will of course depend on the situation.
Maybe one change logically supercedes the other, or maybe they can be merged somehow.
You should edit the file to your satisfaction and remove the `<<<<`/`====`/`>>>>` markers when you're done.
Once you have resolved all the conflicts (note that there can be several conflicting files, and also several conflicts per file), `git add` all the affected files and then `git commit`.
You will have an opportunity to write the merge commit message (where you should describe how you did the merge).
Now you should be able to push.
## Caveat: pull before you start working
Before you start working, **always `git pull`**.
That way, you'll be working from the latest version of your code, and you'll be less likely to have to perform a merge later.
## Caveat: commit your work before you pull
If you make changes and do not commit them before doing a `git pull`, Git may download changes but then refuse to try to do a merge because it's worried about overwriting your uncommitted work.
If you make a commit and then try `git pull` again, it might say `Already up to date` even though the changes haven't been incorporated.
If you accidentally run into this situation, `git merge master` will force the merging process to happen.
The commit-before-pull rule is not the only way to solve this problem, and it has the side effect of creating unnecessary merges, but it's the right approach to start with.