Basics
Git is a development version control tool. Instead of referring to the various Git cloud platforms (such as GitHub, GitLab, Bitbucket or others), we will use the generic term GitSmeg.
Get Git Access
You need access to your organization’s GitSmeg repositories. You may have to ask your local Git administrator for access.
Setup Your GitSmeg Credentials
Important
When you start out, make sure to setup your github credentials and identifying username and email. This is to assist your team in tracking and documenting development history:
git config --global user.name "Jane Smith"
git config --global user.email "janesmith@acme.com"
git config --global push.default simple
git config --global init.defaultBranch main
git config --list # Print default settings
Clone a Repo
To clone (download) a repository from the web:
Find the repo online and get the code string.
Copy that string. e.g., “git@github.com:acme/mousetrap.git”
Pull a repo down with “git clone”
[bash]: git clone git@github.com:acme/mousetrap.git
- or for https -
[bash]: git clone https://github.com/acme/mousetrap.git
Changing Branches
Change branches with checkout. Try these examples:
[bash]: git checkout develop [bash]: git status [bash]: git checkout -b feature/area51 [bash]: git status [bash]: git checkout - [bash]: git status
Committing Changes
Once changes are made you must commit (and push) changes to safely store them:
Change branch to “feature/area51”, change stuff, push:
[bash]: git checkout feature/area51 [bash]: vi conf.py # Make changes to file, write, exit editor [bash]: git commit -a # In the editor, make commit message, write, and exit [bash]: git push # Pushes changes up to GitSmeg [bash]: git log # Inspect the change history
Recommended Commit Message Format
We regard the Git log as an important way to track down and summarize changes in our code. Therefore, it is critical that commit messages are as clear and concise as possible. Remember that the summary line carries large weight in 50 characters.
Note
Here are the rules for commit message
First line is Capitalized description, under 50 chars, no period
Second line blank
Third line states defects: Fixes ACME-13123, ACME-34345, and ACME-99099
Fourth Line blank
Next lines are limited to 72 charactors, elaborate description. It is a bit more open.
Here is an ideal short commit message:
Correct the instance-table relations in the modeler
Fixes ACME-123455.
Here is a more description of the fix (if needed). You wrap to 72
chars to keep it readable.
If your commit is bigger and you need more bullets or description, do this:
Correct the hyper-drive:
Fixes ACME-123455, ACME-92548.
We had to fix the relationships to preserve the original model structure.
We still limit this description to 72 chars to avoid ugliness.
I also added another tire to the system so that it would roll better.
These are other things I have fixed:
* Fixed model to keep old model intact
* Added migration script to ensure model was correct at upgrade
* Added a big fat tire for better rolling
* Updated docs
Reasons for this Format
Why do we prefer this format? Because it allows a quick history view with a command:
git log --decorate --graph --oneline --date-order
If the first line is just ‘Fixes ACME-XYZ123’ or worse you get things that are not helpful at all:
|/ /
* | c568cfe Merge pull request #93 from acme/feature/ACME-22568
|\ \
| * | a367040 (origin/feature/ACME-22568)
|/ /
* | 160f150 Merge pull request #99 from acme/feature/ACME-22599
|\ \
| * | f2d37aa (origin/feature/ACME-22599) fix typo
… instead of somthing readable and useful:
|/|
* | 8f38040 Merge pull request #106 from acme/feature/ACME-22673
|\ \
| * | 58f9857 (origin/feature/ACME-22673) Add default values to properties; fix ACME-22673
|/ /
* | f18a2ac (feature/ACME-22598) Merge pull request #99 from acme/feature/ACME-22639
|\ \
| * | 01d4868 (origin/feature/ACME-22639, feature/ACME-22639) Ensure modeling on Mars
… there are other reasons too. See references.
References:
Typical Workflow Scenario
The typical workflow for any changes to files is:
Create a new branch
Add, change, delete files from the branch
Commit your changes
Push your changes
To create new branch:
git checkout -b branch_name
To add new files:
[bash]: git add -a abc.py def.py
[bash]: git add -A folder # (adds and removes files from tree)
To commit all changes execute:
[bash]: git commit -am "Message that explains changes"
To finally push up your changes to your repo upstream:
[bash]: git push
New Repo Workflow Scenario
Go to GitSmeg website
Create an empty repository in the GUI, and get the repo URL
Now on your workstation, clone the empty repo:
[bash]: git clone https://github.com/acme/bogus.git [bash]: cd bogus/
Start writing your code, make files.
Add files to your repo and push:
[bash]: git add -A [bash]: git commit -a [bash]: git push [bash]: git status .... .... .. Already up-to-date ..
Merging Branches
Once you are satisfied with work done in develop, merge it into master.
First change branches from develop to master:
[bash]: git checkout master
Now things are as before with master in its original state.
Now you want to merge from develop:
[bash]: git merge develop Updating 1530600..2873dc4 Fast-forward .gitignore | 2 + Makefile | 11 +- ...
Now you must push these changes up to your GitSmeg:
[bash]: git push Total 0 (delta 0), reused 0 (delta 0) To git@github.com:acme/mousetrap.git 1530600..2873dc4 master -> master
Delete Unwanted Branches
If you want to eject unwanted branches from your repo, make sure to read the git-branch docs and the warnings about being fully merged (–delete option).
To remove a local branch:
git branch -D <branchName>
To remove a remote branch:
git push origin --delete <branchName>
Synchronizing Local Branches and References: Pruning
Sometimes you’ll have a junkyard of old remote branch references that have been long deleted on the hub. You can synchronize them with fetch:
git fetch -p
Revert a Branch to a Prior Commit
git revert will create a new commit that will undo what the prior commit(s) have done and put that into your history. It gives you a log of your undo.
Resetting a Branch to a Prior Commit
git checkout feature/area51
Identify the number of your last “good” commit:
git log (grab the good commit number: e3f1e37)
Reset your feature/area51 to that commit level:
git reset --hard e3f1e37
Push it up to GitSmeg:
git push --force origin feature/area51
Test the diff between local and remote: Should show nothing:
git diff feature/area51..origin/feature/area51
Comparison of Git Branches
Show only relevant commits between two git refs:
git log --no-merges master..develop
Avoiding Many Small Commits
You can make as many small changes as you like and still have a clean single commit by using git’s amend flag on your commit:
git commit --amend
(make your commit message)
(write/quit)
Every time you make a new commit in this way, you get the benefit of small incremental changes and a clean commit log. If you have already made a mess of things you can try the next technique to Squash your commits.
Squashing Multiple Commits
This allows you to take a lot of many small commits (and their messages) and convert them to a single coherent commit. It keeps the history clean and clear.
In order to do this safely, we recommend only doing this in a feature branch (based on develop) that is not being shared.
Version I: Squashing Against a Prior Commit
Background: You created a branch and made some commits. You want to squash all your small commits into a single unified commit, starting that the root of your branch. The commit just BEFORE your changes is abc123def456.
From your feature branch: If you have made several commits starting from (and not including) commit abc123def456, you can squash all your commits with a rebase:
git rebase -i abc123def456
When it shows you your commits:
pick 01d1124 Adding Goods pick 6340aaa Moving my period pick ebfd367 Hyde has become self-aware. pick 30e0ccb Make my typo nice.
edit this to become:
pick 01d1124 Adding Goods squash 6340aaa Moving my period squash ebfd367 Hyde has become self-aware. squash 30e0ccb Make my typo nice.
Now you write this out and to fix-up the commit logs in the next screen. Do this by changing to a single unified commit message:
Feature ACME-1234: Adding Goods * Moving my period * Hyde has become self-aware. * Make my typo nice.
then write it out.
Now you have to force push, because now git is confused:
git push -f
Version II: Squashing Against a Major Branch
From your feature branch, do a rebase with the -i flag:
git rebase -i develop
When it shows you the multiple commits, change command in commits after the first “pick” to “squash”. Thus this:
pick 01d1124 Adding license pick 6340aaa Moving license into its own file pick ebfd367 Jekyll has become self-aware. pick 30e0ccb Changed the tagline in the binary, too.
now becomes:
pick 01d1124 Adding license squash 6340aaa Moving license into its own file squash ebfd367 Jekyll has become self-aware. squash 30e0ccb Changed the tagline in the binary, too.
Now you write that out and it will ask you to fix-up the commit logs. Do this by changing to a unified commit message:
# This is a combination of 4 commits. # The first commit's message is: Dr Jekyll's final revisions to persona. - Add that license thing - Moving license into its own file - Jekyll has become self-aware. - Changed the tagline in the binary, too.
Once you write that out, you need to push it up with force flag to rewrite history:
git push -f
If you have already pushed it up prior to this, or even created a Pull, your upstream commits and pulls will get replaced with the unified commit.
Git Stash: Stashing Modified Files
Git’s stash option allows you to put modified files into a temporary holding area. The usual scenario is to stash your mods away then pull from the origin, and then re-place your stashed files into the tree. Then you can push the results back up to origin. Here is a possible workflow:
.... you made changes to develop, but you'd rather it be in a feature....
[bash]: git stash
> Saved working directory and index state WIP on develop: e38b798 post
release: 1.0.1 -> 1.0.2dev.....
[bash]: git checkout -b cleanup_on_aisle_7
> Switched to a new branch 'feature/cleanup_on_aisle_7'
[bash]: git stash pop
.... now you have your new mods overlaid ....
.... make whatever other modifications ....
.... now you can commit all your mods ....
[bash]: git commit -a
[bash]: git push
Cool Ways to Show Logs and Diffs
Often you will need to see your logs and compare different versions:
git log
git log --oneline --graph --decorate --all
git diff
git diff fe492a1 #(between current and some other node)
git diff be158f6 aee7163 #(between two nodes)
Git Warnings and Errors
You may you get this warning when trying to push a new branch to origin:
[bash]: git push fatal: The current branch develop has no upstream branch. To push the current branch and set the remote as upstream, use git push --set-upstream origin develop
Although usually safe to follow the suggestions, use caution.