Git
- Synchronising SVN and Git
- Configuring Jenkins CI to work with Git on Ubuntu
- To check out: Using Git on Windows
- My understanding of SVN and Git
- statgit - generate Git development statistics
- Getting Git to work over SSH in Windows
Nifty aliases
Latest 20 commits, with git latest
:
git config --global alias.latest "log --pretty='%C(yellow)%h %C(cyan)%cd %C(green)%aN%C(auto)%d %Creset%s' --graph --date=relative --date-order -20"
Latest 5 tags, with git latest-tags
,
using version order:
git config --global alias.latest-tags "for-each-ref refs/tags/ --count=5 --sort=-version:refname --format='%(refname:short) - %(contents:subject)'"
Things SVN can do that Git can’t
- Checkout into a non-empty directory; you have to checkout into a temporary directory, move the .git folder into the non-empty directory, and run a
git reset --hard
- Add an empty folder. It’s impossible in Git!
.keep
files everywhere! - Store passwords on Windows without having to first install some horrible abomination of Cygwin/credential stores/SSH agents, or having to use the GUI client. (Setup SSH for Git and updating Git to use SSH instead of HTTPS)
- Display
--help
information without opening up aman
page or a web document (if using Windows?). The--help
flag should only print out a summary of help information to the command line. - Keep track of resolved conflicts in other branches when merging the same branches together later on (unless
rerere
is enabled, which it isn’t by default). - Merge any branch into any other branch without later breaking history. In Git you can’t ever merge a branch into another branch because this will mess up history, and possibly cause a commit loop in the future.
- SVN can never have a commit loop unless you’re really trying hard (and editing metadata manually).
- Have multiple mainlines. In Git you can only ever have one mainline otherwise you risk having commit loops.
- Keep track of which branches a commit has been on. In Git, branches are entirely local to developers, and once they are merged and deleted remotely the history is completely lost (unless a non-fast-forward merge, in which case you’ll have a commit stating there was a merge), because the commits are replaced into the target branch. The best case scenario is <a href=”http://stackoverflow.com/questions/4535251/show-the-original-branch-for-a-commit”
if you still have the branch in your local repository</a> or the branch has not been deleted remotely yet.
- Do more than one reverse merge from a previous commit, without having to perform an intermediary commit. “
revert
is not possible because you have unmerged files.” You would need to usegit revert --no-commit
instead.
Things you should never do
git checkout branch; git merge master
git push; git rebase
git merge
(always use--no-ff
, I don’t know why this is even a Git default)
Branching
Create a branch:
git branch (new-branch-name)
- create a new branch, does not switch to branchgit push origin (new-branch-name)
- ??git checkout (new-branch-name)
- switch to branch and update local copy to branchgit commit -p
- commit changes to local Gitgit push --set-upstream origin (new-branch-name)
- push local Git changes to remote Git
Switching branches:
git checkout master
- switch back to master and update local copy to mastergit pull
- download remote Git to local Git
git checkout master
- switch back to master and update local copy to mastergit pull origin master
- update local Git from remote Gitgit merge (new-branch-name)
- do the merge from the given branch (I don’t know what happens with conflicts!)git push origin master
- push local Git to remote Git
Merge two different branches (e.g. you are working on target and want to merge in branch source):
git checkout (target-branch-name)
- switch back to master and update local copy to mastergit pull origin (target-branch-name)
- update local Git from remote Gitgit pull origin (source-branch-name)
- update local Git from remote Git, merge in branchgit merge (source-branch-name)
- do the merge from the given branch (usegit mergetool
to handle unresolved conflicts)git push --set-upstream origin (target-branch-name)
- push local Git to remote Git
Revert a branch merge on another branch without destroying the commits used elsewhere (technically just reverse merging):
git checkout (target-branch-name)
git revert HEAD^
-^
means revert back the last commit on this branchgit revert HEAD^^
-^^
means revert back the second-last commit on this branch (Git cares not about the order of commits on a branch, only individual commits with no relationship to each other!)git commit && git push
- add commit message, push the reverse merge to remote Git
Other commands:
git merge --abort
- revert a mergegit diff --cached myfile.txt
- see the diff of a staged file (i.e. already been resolved)git reset --hard
- throw away all local changes including any committed, but unpushed, changesgit checkout myfile.txt
- analogous tosvn revert myfile.txt
Merging with TortoiseMerge
I really like TortoiseSVN’s merge tool, and with a bit of wrangling you can get Git to use it too.
Add the following files to Program Files (x86)/Git/share/git-gui/lib/mergetool.tcl
just before the error_popup [mc "Unsupported merge tool '%s'" $tool]
block:
tortoisemerge {
set cmdline [list TortoiseMerge.exe -base:"$BASE" -mine:"$LOCAL" -theirs:"$REMOTE" -merged:"$MERGED"]
}
And then you can run GUI merges using git mergetool -t tortoisemerge
.
Your configuration specifies to merge with the ref ‘branch’ from the remote, but no such ref was fetched.
~$ git checkout my-branch
Switched to branch 'my-branch'
Your branch is behind 'origin/my-branch' by 3 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)
~$ git pull
Your configuration specifies to merge with the ref 'my-branch'
from the remote, but no such ref was fetched.
This is secret Git speak for “your remote branch no longer exists”. Try running a git remote prune origin
to remove all branches that no longer exist on remote.
Having two remote repositories
git clone https://github.com/original/foo
git remote add thirdparty https://github.com/better/foo
git push -u thirdparty master
git pull -u thirdparty
Getting the Github patch for a commit
Append .patch
to the end of the commit URL, e.g. https://github.com/soundasleep/cmis/commit/70303e60d437c1c0ee650bcf820c3a13dd4782d1.patch
Revert a merge before it’s pushed
You have to use one of:
git reset --hard COMMIT_HASH
git reset --hard HEAD~1
(thanks @charliesome)
Git LFS conflicts from changing tracked assets
$> git reset --hard
Encountered 1 file(s) that should have been pointers, but weren't:
core/assets/tile1.png
HEAD is now at ...
$> git pull
Updating aaa..bbb
error: Your local changes to the following files would be overwritten by merge:
core/assets/tile1.png
Please commit your changes or stash them before you merge.
Aborting
The only way I found to fix this was to git rm --cached core/assets/tile1.png
and then immediately git add core/assets/tile1.png
, and
then submitting this as a commit git commit
. (via StackOverflow)
Note that GitHub doesn’t like displaying this commit: