We also have a shorter, less-complete git writeup you may consult.
On a single machine, a file can be in one of four states:
State | Meaning |
---|---|
untracked | on your disk but not being tracked by git |
modified | tracked by git, but the on-disk copy doesn’t match git’s copy |
staged | git plans to track the on-disk copy next time it commits something |
committed | tracked by git, and the on-disk copy matches git’s copy |
The command git status
will show you the untracked, staged, and modified files. Files not shown by git status
have been committed.
git add
myfilegit commit -m "
description of changes"
git commit -a -m "
description of changes"
Git keeps a history of all committed files, which can be viewed using git log
.
When working with a client (usually your laptop) and a server, each has its own copy of the files, which can be untracked, modiied, staged, or committed individually on each computer. The only time the computers talk to each other is when you ask the client to git pull
or git push
git pull
Copies all committed changes on the server to the client.
What happens depends on the history of commits on the two computers:
The client tries to merge the server’s history into its history.
Fast-forward merges can occur if there’s no conflict between the changes: for example, if the server modified file X which the client didn’t modify, the client grabs the server’s copy of file X.
If there are conflicts, the merge may require you intervention to resolve.
git push
Copies all committed changes on the client to the server.
The server will refuse the pull unless the server’s current state is part of the client’s history. Because of this limitation, git pull
(which will sync the two chronologies) should always be run before git push
.
Hence the common case on the client is:
git commit -a -m "
description of changes"
git pull
git push
ssh
into
Let’s assume you want to put the project in directory projects/proj1
mkdir -p projects/proj1
cd projects/proj1
git init -b main ./
git config receive.denyCurrentBranch updateInstead
echo "Initial commit" > README.md
git add README.md
git commit -m 'Initial commit'
The -b
in step 3 tells the server to store both the files and the repository structure in the same directory. Step 4 tells the server to automatically accept anything you push to it.
Feel free to change steps 5 and 6 to make a different initial filename and contents. It may be possible to skip steps 5–7 entirely, but sometimes that causes strange errors in the laptop steps noted below.
Let’s assume you want to put the project in directory school/work/myproj1
cd school/work
git clone
yourusername@
the.server.edu:projects/proj1 myproj1
cd myproj1
If you have more than one computer, you can repeat steps 8–10 on each of them.
git pull
git add
any new files you’ve createdgit commit -a -m "
description of changes"
git push
Note: to avoid merges, don’t make edits on any other computers between steps 1 and 5 above. If you did edit on another computers in the middle, add another git pull
before the git push
.
git add
any new files you’ve createdgit commit -a -m "
description of changes"
Warning: Your laptop won’t be able to git push
or git pull
in between steps 1 and 3 above.
Using git on a single machine makes it simpler (there’s no push and pull to worry about) and enables the chronological views (as well as branching) of git, including the ability to recover an earlier version of the project.
The two most important commands for inspecting things are git status
and git log
.
git status
git log
Shows your entire history of commits, with the most recent on the top.
If you have more than a screen full of entries in your log, git log
will run in a pager, a program for showing more than a screen of text on the command line such as less
. Scroll up and down using arrow keys or page up/page down keys. Exit the pager using q
.
If you realize you’ve committed changes you don’t like and want to get back to an earlier commit, there’s a bit of work to do. This work is based on git’s belief that nothing should ever be lost: you might change your mind about the undo later. Git thus gives two options for undoing commits: reversing and branching.
One way to think about an undo operation is as a new operation that just happens to do the opposite of an earlier operation. For example, consider the following sequence:
abcd
ef
to the end, creating abcdef
-
in the middle, creating abc-def
-
from the middle, creating abcdef
Step 4 in this sequence is an reversing-type undo: a new action added to the history that happens to undo a previous action.
The command to do this in git is called git revert
and it requires the specific commit action(s) to undo.
git revert HEAD
HEAD is a special git variable that means the most recent commit
.
git revert HEAD..HEAD~3
The ~
here means minus
, so this reverses the four commits HEAD, HEAD − 1, HEAD − 2, and HEAD − 3.
Each commit in the log has a long hex identifier, like commit 985baf822fa1a3221a892833b0622858a6c75694
. You can pick any one of them and git will try to figure out what the repository would have looked like if everything before and after than had happened but that one thing had not.
git revert 985baf822fa1a3221a892833b0622858a6c75694
In most cases, you can use a prefix of the hex identifier instead of the whole thing
git revert 985baf82
git revert HEAD..985baf822fa1a3221a892833b0622858a6c75694
It is worth noting that reverting the HEAD twice does not reverse two commits: the first revert adds a new undo
commit, which the second undoes, so git revert HEAD; git revert HEAD
leaves all files in the repository unchanged but adds two new commits to the log.
Another way to think about an undo operation is to think of a tree of versions. I always have a point in the tree I think of as now
and when I undo I’m simply changing my point of view. For example, consider the following sequence
abcd
ef
to the end, creating abcdef
-
in the middle, creating abc-def
abcdef
c
and add a q
in front, creating qabdef
In the end I have this history, where the part I am looking at currently is circled in red:
To deal with branches, git uses names. By default when you make a new git repository you have one named branch, typically either master
(for older versions of git) or main
(for newer ones). If you want to undo in a branching way, you need to name your new branch.
git branch
In the list, your current branch is shown with an asterisk in front.
git branch -m
oldName
newName
Because renaming could confuse people working collaboratively, renaming only works on your local copy. You can’t push a rename to the server nor pull it from the server.
Each commit in the log has a long hex identifier, like commit 985baf822fa1a3221a892833b0622858a6c75694
. You can switch to a new branch pointing at one of these by running
git checkout -b
newBranchName 985baf822fa1a3221a892833b0622858a6c75694
When you git push
after making a new branch, you’ll get a special message explaining how to create the branch on server too.
git switch
branchName
Each copy of the repository has it’s own working branch. You can’t push a switch to the server nor pull it from the server.
Note that almost all of git’s commands (commit
, push
, pull
, etc) only apply to the current branch.
Branches can also be merged, but that is out of scope for this writeup. See https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging for more.
To do: write up basics of merges and using github/bitbucket