Here we have a bunch of real-world use-case examples of git, which is #hellarad.
Git Vocabulary
Things are slightly different in git from what you may be used to. Here are a few terms we'll be throwing around and what the intended meaning is.
- repo
- Typically a local working directory that is a git repository as identified by the presence of a
.git
directory. - branch
- A set of tracked changes in a repo, master is the main branch.
- remote
- Othet repositories that the local repo knows about, such as the project origin and perhaps an upstream
- upstream
- A more authoratative code base of the project, such as a central repository.
Quick Steps
Quick steps for working with an up-stream repo
git clone git://git.evergreen-ils.org/OpenSRF.git git log --stat git checkout -b my_work # hack away git commit -a git checkout master git merge --log --stat --no-commit my_work git commit -a git checkout my_work git log --stat
Read-Only Projects
A very common use for git is to just get access to the latest code from the publisher. In this case we clone and pull, over and over. In this example we are working with OpenSRF.
. # git clone git://git.evergreen-ils.org/OpenSRF.git . # git remote -v . # git pull . # git branch -a . # git checkout remotes/origin/rel_2_1
Then I just configure, make && make install and we're ready to go.
To update this git from the origin again we simply go back to the master branch, then pull.
. # git checkout master . # git pull
Viewing Repository Information
There is loads of git repository information stored in the ./.git
directory.
. $ git status . $ git branch -a . $ git remote -v . $ git log --graph --stat
Make a new Project
Making a new project is easy and git will initialise itself in the specified directory. Now git is tracking changes, to any/all files. This is useful for both code (common) and also configurations.
- Track Changes in ~/coolapp
~ # mkdir coolapp . # git init . # git add . . # git commit -m'initial commit'
- Track Changes in /etc
~ # cd /etc . # git init . # git add . . # git commit -m'initial commit'
- An entire installed application, then creating a branch of this first state
~ # cd /opt/freeswitch . # git init . # git add . . # git commit -m'initial commit' . # git branch square-one
Tracking Changes
Tracking changes is done in a git branch. Create one, then checkout to make it the active branch. Then hack away, edit files, delete them, add new ones, make symlinks and all that other fun stuff. A commit will then create a snapshot of your changes.
View local, remote or all branches
. # git branch . # git -r branch . # git -a branch
Discarding Changes
If the files are unstaged you can simply do a checkout, or stash to save them for later. If they are staged use reset
git checkout path/to/changed/file.c
To discard all changes
git checkout -- .
Save the changes for later
git stash git stash save --keep-index
git reset -- path/to/staged/file.c
Create Branch from head, existing branch or tag.
. # git branch new-name-here . # git branch new-name-here copy-from-this . # git checkout new-name-here
Create and Checkout
. # git checkout -b new-big-edit
Push Branch to Remote
git push -u origin my-branch-name git push -u origin my-branch-name
Rename a Branch
. # git branch new-cool-name-hax0r . # git -m new-cool-name-hax0r bug4321 . # git -M new-cool-name-hax0r existing-branch-name
Merging a Branch
Here we'll merge to master, or merge to master w/o a commit
. $ git commit . $ git checkout master . $ git merge bug4321 # don't commit . $ git merge --no-commit bug4321 # bring logs, show stats . $ git merge --no-commit --log --stat --verbose bug4321
Delete a Branch
After the branch is merged to master we can remove it, to keep things clean. If the branch has been pushed then you need to remove it from origin as well.
First example is just deleting the local branch, then force deleting - if there are untracked changes. Finaly, push the delete to the origin. Note the ':' in front of the branch name.
. # git branch -d branch_name . # git branch -D branch_name . # git push origin :branch_name
Amend/Edit Git Commit
This one is quite easy, if the comit was missing some changes.
git add file/you/edited.txt other/file/too.css git commit --amend
Undo Git Commit
This first option destroys the commit as if it never happened, your edits will be lost.
You can undo one or more commits this way.
The first one rolls back the commit, but leaves the files as they were (staged for commit)
Using --hard
removes the edits you've made to the file.
Each ^
is moving the state back one step.
git reset --soft 'HEAD^' git reset --hard HEAD^ git reset --hard HEAD^^
The --soft option will undo the commit, however your edits will remain in a now uncommitted state.
git reset --soft HEAD^ git add edited/file/one.php edited/file/two.css git commit
Revert Single Commit
Viewing Changes
Git provides the diff, log and show commands to view changes to the branches.
. # git diff HEAD^..HEAD . # git diff HEAD^^..HEAD . # git diff --name-only HEAD^..HEAD . # git log . # git log -3 . # git log HEAD^^^^^^^^..HEAD . # git show -2 . # git show --summary
Viewing previous version (^) and previous-previous(^^) versions, file names only, negative numbers reference back from HEAD. Same style inputs for log and show commands.
Patching a git diff
You can apply the output of a git diff as a patch, just like you did back in the days before nice distributed source control.
git diff master my_branch_is_cool > diff.patch patch -p1 < diff.patch
Upstream Remotes
Attach to Upstream Project
In this scenario we create a fork of some other project (on github) and begin working on it. Use github to create the fork, then pull this new forked-master, attach the upstream remote and begin working.
~ $ git clone git@github.com:edoceo/evergreen ~ $ cd evergreen . $ git remote add upstream git://github.com/evergreen . $ git pull upstream master
First the clone is taken, we change to the repo directory and add a new remote named upstream which references the original project. The fetch brings their changes in.
Staying in Sync
It's important with git, and other source control systems, to not get too far behind. However, I've found git to be much more tolerant likely due to it's branch/ref design.
SSH Key Identity Management
In many cases it's possible (probable?) that one would need to have multiple identies on some server. For example, a personal and also company account on GitHub or GitLab. These tools use ssh to push and pull from the remote. And if you have only one SSH key, there will be access control issues. This is solvable with entries in `~/.ssh/config` and then some updates to the remote url.
Host alpha.github.com HostName github.com IdentityFile ~/.ssh/id_ed25519_alpha Host bravo.github.com HostName github.com IdentityFile ~/.ssh/id_ed25519_bravo
See the difference when accessing via ssh now
ssh -T git@gitlab.com Welcome to GitLab, @default! ssh -T git@alpha.gitlab.com Welcome to GitLab, @alpha! ssh -T git@bravo.gitlab.com Welcome to GitLab, @bravo
Then we re-write the remote origin url using the alias defined in .ssh/config
$ git remote -v origin git@gitlab.com:edoceo/example.git (fetch) origin git@gitlab.com:edoceo/example.git (push) $ git remote set-url origin git@alpha.gitlab.com:edoceo/example.git