Skip to content
This repository has been archived by the owner on Feb 1, 2020. It is now read-only.

Git FAQ

dwightguth edited this page Jan 28, 2015 · 10 revisions

This page is broken down by use cases. Look for the heading that describes what you are trying to do, and follow the instructions.

Setting up git (do this once)

Github's own instructions for setting up git are here: https://help.github.com/articles/set-up-git

Especially if you don't have a new enough git to have "credential helper", you may want to set up an SSH keypair (and maybe let ssh-agent save you from retyping the password) https://help.github.com/articles/generating-ssh-keys

Note that only SSH clone urls are subject to SSH keys.

Create a fork (do this once)

  1. Go to: https://github.com/kframework/k
  2. Click the "Fork" button in the upper right, then select your personal account.
  3. In your git console, run git clone with the argument in the right sidebar on github. For example, Dwight runs git clone https://github.com/dwightguth/k.git. If you normally connect to git via SSH (e.g. because you want to specify an SSH key), you would use the SSH clone URL: git clone [email protected]:dwightguth/k.git.

Create a new clean branch to contain your change

In order to simplify the process of manipulating changes, it is often very convenient to have a local branch named "master" which tracks "origin" and contains no local changes. This allows you to easily create new clean branches by running the command git checkout -b <branch_name> master. These branches then contain your changes so that the "master" branch remains unmodified and in sync with the main kframework repository.

To create a new feature branch to commit your changes to, run the above command. However, if you already have made changes to your local "master" branch, it is advisable to move these changes onto a feature branch. To do this:

git checkout -b <branch_name> master # this creates a branch containing your changes so they are not lost when you rebase master
git checkout master # move back to master branch so that the following command works correctly
git reset --hard upstream/master # reset working copy and all local commits to the upstream/master which is clean

By making your changes only on branches of your local "master" branch, you simplify the process of merging, rebasing, moving changes between branches, etc.

Creating a branch of a branch

Sometimes you want to branch off a branch other than master, for example when you are working on a long-running feature branch and want to submit code reviews, or when you are working on a change that depends on another change which has not yet been merged into master. To do this, you have two options.

  1. Run git checkout -b <branch_name> from the branch you wish to branch off of.
  2. Run git checkout -b <branch_name> <branch_to_branch_from>. The first of these is equivalent to the second with the caveat that <branch_to_branch_from> becomes the current branch. For more information, see git help checkout.

Pushing changes

By default, when you run "git push", you might see the following message:

warning: push.default is unset; its implicit value is changing in 
Git 2.0 from 'matching' to 'simple'. To squelch this message 
and maintain the current behavior after the default changes, use: 

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use: 

  git config --global push.default simple

Personally I recommend using simple to avoid accidentally pushing to branches you don't want to push to, but it's up to you. Just make sure you never push changes to the master or nightly branches of the main K framework repository (i.e. upstream). The easiest way to ensure this is to never commit changes to these branches. See the previous section for more details.

Create a pull request

  1. Log into github and click "Pull request" next to the line that says "This branch is commits ahead and commits behind master".
  2. If you are pulling into a branch other than master, make sure you click "Edit" at the top and then select that branch where it says "Base".
  3. Make sure you are submitting the correct change, type up a description for it, then submit it. This automatically emails everyone watching the K framework repository except yourself.
  4. If you need a particular user to review your change, you should tag their Github user ID in the pull request description. For example to ask me to review something you might say "@dwightguth Please review."
  5. At this point it becomes the responsibility of reviewers to comment on your change and either approve it or request modifications. They can do this by accessing the pull request online and commenting on the change or on specific lines of code. If they request changes, you can update the pull request simply by pushing further changes on the same branch to your fork. Once the pull request is approved, you are free to click the "Merge pull request" button on the bottom of the pull request screen to automatically merge and close the pull request.

Continuing to work after submitting the pull request

  1. Note that any push made to the same branch after the pull request is opened but before it is closed will add that commit to the pull request. To continue working on a different change during that time period, you must work on a branch.
  2. Create a short-term feature branch in your fork by running the command git branch <branch_name> <commit_id_to_branch_from>. For example to create a branch named "foo" from the commit immediately prior to the most recent, you might run git branch foo HEAD^. For information on how to specify commits, see git help revisions
  3. Switch to the new branch by running git checkout <branch_name>.
  4. Start making your new change. When it comes time to perform a pull request, push the changes upstream to the branch you created by running git push origin <branch_name>.
  5. Proceed from section "Create the pull request"

Syncing your fork with the upstream repository

  1. (do this once) run git remote add upstream [email protected]:kframework/k.git (or use HTTPS if you prefer). This adds a remote repository to your local repository for the kframework/k repository.
  2. Run git pull --rebase upstream <branch_name> to sync a particular branch of your local repository with the main repository. Do this if your branch is behind the master repository. DO NOT DO THIS IF YOUR CODE HAS ALREADY BEEN CODE REVIEWED. This will destroy the commit history that the reviewer saw when they reviewed, and make it harder to continue the review later. In this case, run git pull upstream <branch_name> in order to merge instead.
  3. Run git push origin <branch_name> to sync your fork with your local repository, which should now contain the latest changes. If you get a message saying something similar to: ! [rejected] master -> master (non-fast-forward) You should try to determine whether or not your fork contains changes that your local repository does not which you want to keep. If it does, you will need to incorporate those changes into your working copy in order to proceed. However, if you are okay with removing the history from your fork which differs from the local repository, you can run git push origin <branch_name> -f to override this error.

Checking out someone else's branch

If the branch is a branch on the main kframework repository

  1. Run git fetch upstream to ensure that you have downloaded the latest version of the remote branch to your local repository.
  2. Run git checkout <branch_name> to check out the branch. Pay attention to whether it says it is tracking upstream or origin.
  3. If it says it is tracking origin, you may be out of date against the main repository, so you should run git pull --rebase upstream/<branch_name>.
  4. If it says it is tracking upstream, this is the first time you have checked out this branch, and you need to push it to your fork. Run git push -u origin <branch_name>.

If the branch is a branch in someone els's fork

  1. Ensure that you have added that person's remote to your repository by running git remote -v and checking for a remote named after their github username. If it is not present, you can add it with git remote add <username> [email protected]:<username>/k.git
  2. continue from the above instructions, except substitute their usename everywhere it says upstream.

Rebasing versus merging

See http://git-scm.com/book/en/Git-Branching-Rebasing for more information on when not to rebase. In summary, don't rebase anything after it has been made publicly available, either by being merged into the main K framework repository, or by being code reviewed by someone else. Before that point, feel free to rebase your changes however you like in order to make your history more to your liking.

Visualize status

git status will tell you what branch you are on, and summarize changes you've made, divided into the changes you've staged (marked to include in your next commit), and other changes. It also includes useful reminders of the commands to unstage or to completely forget and overwrite the local changes. With the --ignored flag it also lists all files that exist but are covered by the .gitignore files, in case you want to check on that.

gitk displays a graph of the commit and branch history starting from whatever you've checked out, annotating any of the older commits that happen to be the head of some branch or tagged with some tag, and letting you inspect lots of things. It can take as arguments as many local branch names like and remote branch names like origin/ as you like, and then will show a combined graph including history back from each of those points. (there are tons of extra options and argument forms you can find in man pages, one particularly useful form is <branch>...<branch> to show only commits from the two branches back up to common ancestors, if you are thinking about a merge).

Recover a deleted file

The command git checkout -- <file> will overwrite file with it's contents in whatever version you have checked out, replacing deleted files and overwriting modifications. The easiest way to use it is probably to run git status whose output includes a reminder of this command and a list of all (non-ignored) modified and deleted files so you can just copy and paste filename.

"svn up" was used to replace deleted files, "git pull" doesn't do that because it considers deleting files to be possibly an intentional local change that it doesn't want to overwrite.

Fixing problems rebasing

Sometimes you try to rebase changes in order to sync your branch with the upstream repository and run into weird problems where it has conflicts that you don't think should be there, or it adds a bunch of changes that aren't yours to your pull request.

In my experience this is generally because your commit history is not what you expect. Perhaps you have commits in your history in two different places, or you are branched from a different commit than you thought. To resolve this issue, we can use cherry-picking.

  1. From a clean master branch, create a new branch for your change to be transplanted into. To do this, run git checkout -b <branch_name>. If you do not have a clean master branch, see the section "Creating a new clean branch to contain your change".
  2. From your clean new branch, cherry-pick the changes you want. If you have only one change, you can do this by running git cherry-pick <branch_name>. Otherwise, collect the hashes of all the commits you want to cherry pick and run git cherry-pick <hash1> <hash2> ....
Clone this wiki locally