Cheat-sheets
Install Git
Git Bash Setup
Git SSH Keys for Automatic Login
Follow these instructions if you do not want to type your username and password every time you push to git.
- Make a public/private key pair (Acknowldegement: These instructions based on https://confluence.atlassian.com/bitbucket/set-up-an-ssh-key-728138079.html)
- Create the key by running the command
ssh-keygen
- Accept the default location by pressing enter.
- Specify no password by pressing enter again twice.
- Copy the key.
- Print it to the command prompt with
cat ~/.ssh/id_rsa.pub
- Then copy it by selecting it, right-clicking, and selecting copy (Control-C means something different in a command prompt – it means “kill the current program”)
- Print it to the command prompt with
- Go to your user account settings at github.com, go to the section “SSH and GPG keys,” create a new key, and paste the public key into it. Give it a name like “CS3841 VM”
- Create the key by running the command
- Now, github will automatically offer you the ssh-based git pull command.
- If you have not cloned the project yet, go to the project page, select “Clone” and “Use SSH” if it is not already showing the SSH URL:
Copy the SSH URL: - If you already pulled it with https, get the new url and reset the url with a command something like
git remote set-url origin git@github.com:username/repositoryname.git
(Following https://confluence.atlassian.com/bitbucket/change-the-remote-url-to-your-repository-794212774.html)
- If you have not cloned the project yet, go to the project page, select “Clone” and “Use SSH” if it is not already showing the SSH URL:
IntelliJ Setup
To create a new IntelliJ project and check it into a blank Git project:
- Clone the empty repository with
git clone ______.git
where the URL comes from the github page’s “Clone this repository” link. I recommend getting the SSH link rather than the HTTP (once you set up SSH keys as above) - Create a .gitignore file containing
.idea/workspace.xml
out/
- Check this in like any other file.
- Create an empty IntelliJ JavaFX project however you usually do it. Confirm the main window opens.
- Copy the contents of your IntelliJ project into the contents of your empty git repo. Your .idea folder should show up side-by side with the .git folder if you have done this correctly. Ask me for help if it doesn’t. (From the command prompt, use
ls -a
to show folders starting with a dot (.) - Run
git status
. It should show your intelliJ files in red. - Open this folder as an IntelliJ project. While opening it, it should recognize your top level git folder as an IntelliJ Project. If it does not, do not open the project. Ask for my help at that point. (If you open the project, it will create another IntelliJ project, which is undesirable here!)
- Confirm that the window still pops up when you run it from your git project.
- Run
git status
again. (I’m kind of compulsive about this – it’s hard to undo stuff if you make a mistake in Git) - Run
git add .
to add ALL the files that showed in red in the previous command. - Run
git commit -m "Fresh IntelliJ JavaFX Project"
to commit to your local repository - Run
git push
to push the files up to the server
Now, a second teammate should test the repository:
- Run
git clone ____.git
as above (Orgit pull
from within your git directory if you’ve already cloned it). This pulls down the full project from remote to your local repository, local index, and local working directory. - Confirm the .idea folder and src/…fxml file are present.
- Open this folder as an IntelliJ project. While opening it, it should recognize your top level git folder as an IntelliJ Project. If it does not, do not open the project. Ask for my help at that point. (If you open the project, it will create another IntelliJ project, which is undesirable here!)
- Confirm that the window still pops up when you run it from your git project.
Congratulations! You now have a complete starting repository!
I find this tutorial on Git to walk through the sorts of things I would like to teach about Git. This link skips past the setup page, since we do that together in class.
Fancy git log
Want to look at your local history? Git A DOG!
git log --all --decorate --oneline --graph
All. Decorate. Oneline. Graph. A DOG. Get it? :-). Turns out “decorate” is included by default in more recent git versions. But still an easy way to remember this command!
This similar command shows a graphical history similar to what you would see on GitHub. I think –abbrev-commit can be left off without changing the output.
git log --graph --decorate --pretty=oneline --abbrev-commit
And I like this format for grading labs: Shows the author and date, too:
git log --pretty=format:'%C(yellow)%h %Cred%ad %an%Cgreen%d %Creset%s' --date=short --graph
Cleaning up messes in Git
I strongly recommend avoiding messes in the first place:
git status
beforegit add .
andgit commit -m "..."
git diff
beforegit add .
andgit diff --staged
beforegit commit -m "..."
- Frequent commits to the shared branch when possible to reduce messy merges
- Separate branches when development will take more two commits or when intermediate results will break the current dev branch in some way. (Non-compiling commits MUST be off of the master and dev branches and SHOULD contain a clear message that they don’t compile.)
In many cases, the quickest way to clean up a mess is to use the “xkcd approach”.
This can work even if you want to keep your changes:
- Re-clone the project in a new folder besides the old project (
cd
out of your git folder.ls
to confirm you can see your folder, but aren’t inside it. Then clone as you did at first, but specifying a destination folder:git clone _______.git projectN
. I recommend updating N every time you have to do this, and deleting the old copies once you are sure there is nothing you need in them.) - Copy your changes to the re-cloned project. (E.g., if you were in project4, copy your changes to project5)
- Pull, confirm it compiles, then add, commit, and push your changes to the server as usual.
It’s a fail-safe approach! (Then, once you are sure it worked, remember to delete your old directory so you don’t get confused about which one to use!)
There is one case where this does not work well. That is if you have attempted a pull, and the merge that comes as part of the pull fails. If there have been many new changes merged in from the remote branch, you may find it hard to extract the code you want to save. In that case, you may want to roll back to your last commit. Make sure there are no untracked files in your old worspace that you care about and do a reset in your old project using the command git reset --merge
or git reset --hard
. This will undo the failed merge and go back to the version of your code before you did the pull. See the section on wiping your working directory and returning to the latest commit for more information.
I have found there are some subtleties here. I have a flowchart that I wish to typset and place here
So I recommend the xkcd approach if you ever have a mess. But, if you still want to practice your git kung-fu, here we go:
The git mergetool
When you do a git pull
or git merge ...
, git will attempt to automatically merge the changes on your local branch with either the merges from the remote server or whatever branch you specify (respectively).
If their are overlapping changes between the two branches, the automatic merge will fail. Git will not create the new commit. It will instead wait for you to manually edit the files to resolve the conflicts, add the files, and commit them as usual.
However, git does store several versions of the file for which the merge failed: The latest versions from the two branches you are merging (e.g. your local branch and the branch on the server), the original version that both branches are derived from, and the automatically merged version that is in your working directory. (The other three files are in the index somewhere.)
One of the most convenient ways to use these files is to use git mergetool
to view them all at the same time.
When you run git mergetool
, it opens up a window with all four files: The latest commit on the local bracnch on the left, the common anscestor in the middle, and the latest commit on the other branch on the right. Underneath all of these, it shows the merged version that is in the workspace. This can help you to see where the changes come from that show up in the merged version.
However, you need to use an editor that is designed to perform a merge like this. The default editor is vimdiff
, based on the vim
editor. You will need to know a few keybindings to use this editor: Pressing Control-w and then an arrow key will move you between the windows in this editor. The arrow keys (or, if you prefer, j, k, l, and h) will move the cursor around the screen. dd deletes a whole line. Pressing i takes you into insert mode where you can type text or delete existing text. Pressing the escape key takes you out of editing mode.
When you are done editing the file in vimdiff
within the git mergetool
command, you can press :xa and then enter to save and close all files, or :qa! and then enter to close all files without saving. Once you do either of these, the git mergetool
is complete. You cannot start it again without undoing the merge. (If you do want to undo the merge, simply use git reset --merge
. But you might also have to do git status
and the use rm somefile.orig
to delete any files that you edited)
**As an alternative to the command-line git mergetool
, you can use IntelliJ’s built-in merge conflict resolution tool. To do this, identify the file that has merge conflicts in IntelliJ. It should show up in red. Right-click just about anywhere and select “Git->Resolve Conflicts…```. This opens the Files Merged with Conflicts window. Double-click on the file whose conflicts you wish to resolve. You will see a window that looks like this:

Changes in red are the conflicting changes. To automatically resolve the non-conflicting changes, select the All button at the top of the window. When you are done, press “Apply” to save your changes, or “Abort” to close the window without saving them.
Github also released ‘Github desktop’ which has a nice merge conflict resolution tool builtin. However, we prefer that for everything except merges, you learn to do the git management from the command prompt.
Cleaning up a git mess: General notes
For general guides to undoing stuff in Git, see [1] and [5].
Throughout this section, I use the term “working directory” where most poeple would say “working tree” [6]. Both terms mean the same thing in this context: All the folders and their subfolders in my git project, excluding the .git folder itself which is ignored by git.
I distinguish “working directory” (by which I mean the whole working tree) from “current folder and all its subfolders” (which does not include folders above the current folder in the working directory)
Note that IntelliJ also tracks local history, so you can sometimes recover lost files through that even when you have completely removed them from .git (I don’t recommend relying on this behavior!)
Wipe directory and return to latest commit.
If you want to discard EVERYTHING that you have changed since the last commit, use these commands. You can also use these commands if you want to undo a messy git merge
or git pull
, since merge
and pull
do not create a new commit if the automatic merge fails.
These commands wipe out ALL changes since the last commit. You must run them commands from within the topmost folder of your project because the git clean
command only works from the current directory and its sub-directories. [4]
git status # Check to see what we are about to discard.
git reset --hard
git clean -dfxn # Check what the next command will delete before running it.
git clean -dfx
Original source: [2b]
Notes on the flags used with git clean
:
# Add -n to check if you want to remove those files, e.g. git clean -ndfx
# -f: force: You MUST use this option to get ANY files deleted by this command
# (It's required for safety)
# -d: delete directories;
# -x: delete even .gitignored files (which are, of course, not backed up by git)
If you would like to do the equivalent of the xkcd command (without saving anything in your local repository!) see, the section on an exhaustive wipe below.
Individual files
In this section, we undo a git procedure one file at a time.
git reset <filename> # Undoes git add <filename> (Take file out of index without changing
# the contents of the file in the working directory)
# Note that git reset CAN edit much more than one file if you use different arguments such
# as git reset . or git reset --hard HEAD
git checkout -- <filename> # Undoes edits to a file that is not yet staged for commit.
# Note that the -- line helps to distinguish the filename from other git words like origin or master,
# just in case the file is called that. See what happens if you type git checkout -- and hit
# tab: It tells you the special names in this context.
rm <filename> # Removes a file that has never been staged for commit. Such a file is not in the index,
# so you can't check it out with git checkout -- <filename>. Here we are using a basic shell command
# to delete the file instead of a git command since git doesn't know anything about the file.
All files
In this section, we undo a git procedure for the entire working directory. To do this, you must run these commands from the topmost folder within your .git project. Some of the commands (e.g., clean) only work from the current directory and its sub-directories. [4]
git reset # Undoes git add for all files in the entire working directory
git checkout -- . # Undoes edits to all files in the current folder and its subfolders (but not any folders above it in the working directory.)
git reset --hard HEAD # Undoes both edits and add.
git clean -dfx # removes all working directory files that are UNTRACKED in the current folder and its subfolders. These are files that are in the working directory, but are not checked in and have not been added to the index yet. Note that -x means to also remove ignored files!
To undo git commit -m "..."
, please go to the next section.
Whole commits
All the commands we have looked at so far deal with resetting the working directory and the index. But what if you have already committed the files?
This is the best command for “rolling back” to a previous version when things have already been pushed to master:
git revert 0737a # Create a new commit that reverses the effect of previous commits to bring you back to an older commit.
This command creates a new commit that undoes all the changes, restoring the state of the selected commit. The random numbers 0727a are the first few digits of the whole commit hash (e.g, 0737abe3131037765d4806fd6ec5f6353d755c28). You only need to type enough to make the hash unique.
Exhaustive reset to origin/master script
The two commands in the section on wiping your working directory and going back to the latest commit will restore things back to your latest local commit. This script does the equivalent of cloning the repository freshly from the remote repository. But be warned: Unlike the xkcd approach, this will delete all your changes in the local working directory, and may even discard local commits!
git status # Check to see what we are about to DISCARD
git reset --hard HEAD # wipe out working directory and index (except untracked files)
git clean -ndfx # Check to see what we are about to delete.
git clean -dfx # Delete untracked files and directories in the working directory (and perhaps tracked ones as well)
# Or git clean -dffx
# -ff makes the force more forceful (removes untracked directories that appear to be managed by a different git repository [3])
git checkout master # Move to the master branch
git fetch origin master # Pull from master without touching index or working directory
git reset --hard origin/master # Replace your current branch with origin/master. This MAY discard local commmits!
git pull # One final pull from master (maybe just to make sure we're up-to-date a few commands later?)
git status # See how things look. Hopefully clean now!
Original source: [2]
Note: This script assumes that you are not using any sub-modules. A sub-module is a git repository checked out inside of another git repository. We are not using them this quarter. But if you are curious, see the full script [2].
Further Reading
[1] https://gist.github.com/hofmannsven/6814451
[2] https://stackoverflow.com/a/4327720/1048186
[2b] https://stackoverflow.com/a/31321921/1048186
[3] https://git-scm.com/docs/git-clean
[3b] https://git-scm.com/docs/git-reset
[4] https://stackoverflow.com/a/20838589/1048186
[5] https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things
[6] https://backlog.com/git-tutorial/git-workflow/
Acknowledgements
Thanks to Stephen Linn for the fancy git log command