Git
- Pro-Git book online
- For Windows, you probably want Github for Windows which has a UI and command line versions.
Another (free) UI is Atlassian's SourceTree - On a new machine, you need to save your identity into %USERPROFILE% .gitconfig:
git config --global user.name "John Doe"
git config --global user.email [email protected] - The default editor is vim (which you quit with {Esc}:x or {Esc}ZZ). To replace with notepad++:
git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -nosession"
- In a corporate environment, set the internet proxy: git config --global http.proxy http://proxy.northwind.com:80
With username/password: http://user:[email protected]:80/
If the username is in the format "[email protected]", encode the "@": http://user%40corporate.com:[email protected]:80/ - Github for Windows includes a credential helper, so you don't have to keep typing in username/password on the command line for https: just write once
git config --global credential.helper wincred
Files and (local) commits
Files are staged (tracked by git) before they are committed.
git init
to create a new repository,
orgit clone https://github.com/xxxx
to create a local copy of an on-line one.git status
status of a directory,git diff --staged
for diffsgit add readme.md
start tracking a file (or a folder recursively)
If you've cloned, everything is automatically tracked
You can use wildcards:git add *.cs
You can undo the tracking:git reset HEAD *.cs
- ignore files with a .gitignore.
git commit -m "my commit"
commits staged changes to local repository
You can skip staging with -a :git commit -am "my commit"
If you omit the -m, you go into vim (see above to change the editor)
git log
shows the commit history.
git commit --amend
amends the last commit (so have less commits in history- esp for fixing merges)git rm readme.md
to remove,git rm --cached readme.md
to remove and ignoregit checkout -- readme.md
reverts a file (including contents) - aka undo pending changes
Create labels/tags with git tag -a tagName -m 'This is labelled tagName'
Add the commit checksum (or the first unique part of it) to tag a specific commit
Remotes (central servers)
A remote is the central source control server (equivalent to Subversion or TFS).
- The default remote is called origin.
When you forked a repo, you use another remote upstream by convention - The default branch is called master.
- For
git merge
/git pull
there is a "/" between them- git merge origin/master
Forgit push
there is " " space separator: git push origin master - You can add another remote:
git remote add zz https://github.com/ccc
(use a shortname like "zz", like "origin", so you cangit fetch zz
. - You can rename remotes:
git remote rename origin upstream
git clone https://github.com/xxx
creates a local repository from the origin remote
git remote -v
shows the remote(s) with url.
Cloned files are automatically tracked (no need to git add file).
Forked repos
When you fork, you want a link to the origin of the fork- the "upstream".
git remote add upstream https://original-repo/
To update with latest changes:
git fetch upstream
Gets the changes (but no local files changed)- Optional
git checkout mybranch
Change into branch (or master) git merge upstream/master
Merge the local files (in the current branch - you probably want to git checkout master first)
OR:git rebase upstream master
- rebase version of above (see below)
OR:git pull --rebase upstream master
- do a fetch and merge with rebasegit push
to update your "origin" remote with the changed and merged files
Get Latest
git pull
does a git fetch origin
and git merge
to get the latest from the origin.
NB: fetch just gets the data into the .git repository (not files), merge changes the file contents.
Check in
git push {remotename} {branchname}
- pushes commits from branch to remote e.g. git push origin master
.
A push is like a branch merge, but you can only do fast-forward merges. The more common workflow is to do a pull request (not actually a command, but github has a great UI to do it)
Branches
- The default remote server and branch are called origin/master.
- A cloned repository has 2 pointers: the local branch "master" and the remote branch "origin/master"
- The pointer to the current branch is called HEAD
- One strategy is to have a long running develop branch, and periodically "release" by merging into master.
Short-lived topic branches can exist for specific issues.
Unlike Subversion/TFS, you don't branch to a new folder with a different set of files. It's the same folder as the trunk ("master").
git branch branchname
creates a branch (but does not switch to it).git checkout branchname
switches to a branch (points HEAD to branch).
git checkout -b branchname
creates and switches to a branch.git merge branchname
to merge branch into current branch.
A "fast forward" is a simple additive merge. Otherwise you have a new "merge commit" which is a special commit containing the sum from both branches (a "3-way merge" as there are 2 branch parents and a new commit).- Merge conflicts can be edited, then run
git add filename
to mark then merged. - A rebase is a type of aggressive merge, in which one branch is "replayed" over the other. This means the merge is a "fast forward" and the history is cleaner. Don't rebase commits that have already been pushed to a remote.
- Delete a branch with
git branch -d branchname
- Push local branches to server with
git push origin branchname
Workflow
There are several common workflows:
- Centralized (everyone checks into same remote)
- Feature branches (create branches, pull requests to pull into central remote)
- Gitflow (master branch is static, production; everyone branches off "develop" branch and merges into "release" branch(es) which in turn merge into master). Yes, this is complex.
- Github flow (master is always deployable; branch + pull requests; after merge, deploy). For continuous deployment, and much simpler than gitflow. Variations include making release branches when deploying.
Centralized
This is the closest to centralized subversion/TFS source control, is simple and works
- Create central repo.
- Clone it locally. git clone https://....
- Work locally. git add readme.md, git commit -m "my commit"
- Push to central repo. git push origin master
- Fixes:
- if there is a merge problem, update from the central repo: git pull --rebase origin master
Resolve issues, then git push origin master - If you forgot to include files, git add etc, then
git commit --amend
to amend the commit - To squash several commits into one (simplify history), do an interactive rebase
git rebase -i
pick the first, then s[squash] the other commits (or fixup to discard commit messages). - To sync the latest changes from origin (or upstream),
git fetch upstream
Gets the changesgit rebase upstream/master
Reapply all the changes onto the mastergit rebase --continue
over all conflicts
- if there is a merge problem, update from the central repo: git pull --rebase origin master
Feature branches
- For each piece of work, create a branch. git checkout -b mybugfix master
- You can push to master in a branch. git push -u origin mybugfix
After the branch is created, it is tracked, so just git push - Make a pull request
- Any further work in the branch is automatically added to the pull request
- Finally, git checkout master, git pull origin mybugfix, then git push
Tricks
- You can create a windows batch file with git commands, but each command should be "call git", not just "git..."
- You .gitignore a folder, but the contents are already committed.
git rm -r --cached directoryname
You can also:
git rm -r --cached .
(removes everything)
git add .
(add it all back, ignoring what's in .gitignore)
commit/push