Git: Difference between revisions
(→Tags) |
(→Tags) |
||
Line 453: | Line 453: | ||
git tag # list tags | git tag # list tags | ||
git tag -l # list tags | |||
git tag -l <pattern> # list tags matching pattern | |||
git log --decorate # list tags in log | git log --decorate # list tags in log | ||
git tag [tag] # tag current position | git tag [tag] # tag current position |
Revision as of 08:42, 22 October 2024
Subpage Table of Contents
Git
Git - Fast Version Control System
- "Git is...
- Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
- Git is easy to learn and has a tiny footprint with lightning fast performance. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows."
---
- Git is...
- Git is an open source, distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
- Every Git clone is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server. Branching and merging are fast and easy to do.
- "Git is a free distributed revision control, or software source code management project with an emphasis on being fast. Git was initially created by Linus Torvalds for Linux kernel development.
- Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server."
.gitconfig
[user] name = Kenneth Burgener email = kenneth@oeey.com
To set from the command line:
git config --global user.name "Kenneth Burgener" git config --global user.email kenneth@oeey.com
List settings:
git config -l
Empty Email
git config --global user.name 'Snail Mail' git config --global user.email '<>'
git commit --author "Snail Mail <>"
ref: [1]
Name
Linus Torvalds has quipped about the name "git", which is British English slang for a stupid or unpleasant person:
- "I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git."
Custom Bash Prompt
Customize your Bash prompt - makandropedia - http://makandracards.com/makandra/1090-customize-your-bash-prompt
GIT adds a __git_ps1 function that will output your branch. You can add onto it by specifying a string argument. A '%s' in the string will be replaced by the branch. I configured it to also show the short hash. Below is how I did it:
get_sha() { git rev-parse --short HEAD 2>/dev/null } get_hg_id() { id="$(hg id -bt 2> /dev/null| sed -r 's/[\(\)]+//g')" if [ -n "$id" ]; then echo "($id)" fi } PS1='${debian_chroot:+($debian_chroot)}' PS1=$PS1'\[\033[00;32m\]\u@\h\[\033[00m\]:' PS1=$PS1'\[\033[02;48m\]\w\[\033[00m\]' PS1=$PS1'\[\033[00;35m\]$(__git_ps1 "(%s $(get_sha))")$(get_hg_id)\[\033[00m\]' PS1=$PS1'\[\033[01;38m\]\$\[\033[00m\] '
HEAD Alias
HEAD^ vs HEAD~ vs HEAD^3 vs HEAD~3
Rules of thumb
- Use ~ most of the time — to go back a number of generations, usually what you want
- Use ^ on merge commits — because they have two or more (immediate) parents
Mnemonics:
- Tilde ~ is almost linear in appearance and wants to go backward in a straight line
- Caret ^ suggests an interesting segment of a tree or a fork in the road
Caret:
- HEAD^ means the first immediate parent of the tip of the current branch. HEAD^ is short for HEAD^1, and you can also address HEAD^2 and so on as appropriate.
HEAD^ == HEAD^1 HEAD~ == HEAD~1
HEAD^^ == HEAD^2 HEAD~~ == HEAD~2
Commands
gittutorial
gittutorial - A tutorial introduction to git (for version 1.5.1 or newer):
man gittutorial
config
Configure name and email:
$ git config --global user.name "Kenneth Burgener" $ git config --global user.email kenneth@t0e.org
init
Initialize git repository:
git init # current folder git init . # current folder git init [dir] # initialize folder (create folder if needed)
clone
Clone an existing repository:
git clone [repo] # clone [repo] to local dir named [repo] (only current branch) git clone [repo] [newrepo] # clone [repo] to new local dir named [newrepo]
clone reference
To speed up cloning using a local reference:
git clone --reference /local/repo/path ssh://remote_repo new_repo
add
Add files to be tracked:
git add . git add [file1] [file2] ...
undo add
This will undo the git add:
git reset [file]
add removed
To add commits with 'rm' or 'mv': [4]
git add -u
To stage your whole working tree:
git add -u :/
To stage just the current path:
git add -u .
To handle only removed files:
git rm `git ls-files -d` # or git ls-files -z -d | xargs -0 --no-run-if-empty git rm
XY problem: [5]
git commit -a
- which would automatically pick up deletions, committing current state of tracked files in working directory
git add -A
- which would add not ignored untracked files and remove no longer existing files, e.g. if you want to create commit from sideways update of working directory, e.g. unpacking a snapshot or result of rsync.
commit
Commit changes:
git commit # include only 'added' files git commit -a # also include modified tracked files git commit -a -m 'message' # specify message
status
Show status: (shows: Changes to be committed, Changed but not updated, Untracked files)
git status
log
View commit log:
git log git log -1 # show last commit git log -p # diffs at each step git log --stat --summary # overview
git log --stat # show files with change summaries git log --name-only # show files only git log --name-status # show file names with simple mod attribute
git log --name-status HEAD^..HEAD
git log -1 --stat # show last commit stats
git log -n 8 --oneline --graph --decorate
glog
Graphical Log: (ascii art)
git log --graph
--- glog - a git log alias for a decent view of your repo [6]
To create this alias, add the following to your .gitconfig
[alias] glog = log --all --pretty='format:%d %Cgreen%h%Creset %an - %s' --graph
gitk
Graphical Commit Viewer for Git
gitk [file]
gitk --follow [file]
Shows change history of file in nice graphical view.
ref: https://www.youtube.com/watch?v=wkJ4leOuK_o
show
git show # show summary and diff of current position git show --summary # show summary of current position
git id
git show could be used as a git id:
git show git show --summary git show -q # seems to work like --summary but not mentioned
git rev-parse HEAD # hash only git show -s --format=%H # hash only git show -s --format=%h # short hash
.gitconfig:
[alias] id = rev-parse HEAD sha = rev-parse HEAD
diff
See difference between changes and committed:
git diff # Show only changes not added to the index git diff --cached
git diff HEAD..origin # show change between fetch and pull git diff origin/master
git diff HEAD@{1} # show changes since before the last pull git diff HEAD@{1} [filename] # same, but specify file
git diff HEAD^ git diff HEAD^ -- /foo/bar/baz.txt
git diff [shaOfHisCheckIn]^ [shaOfHisCheckIn] git diff [shaOfHisCheckIn]{^,}
After doing a 'git fetch':
git log HEAD..origin
Alias for origin/master:
[alias] difff = diff origin/master
Color Diff
git diff --color=always | less -r
Use less -r as pager:
git config --global color.ui true git config --global core.pager 'less -r'
[color] ui = true [core] pager = less -r
Ref: https://unix.stackexchange.com/questions/19317/can-less-retain-colored-output
branch
Branching:
git branch # list branches - master is default git branch [branch] # create branch git checkout [branch] # checkout desired branch git merge [branch] # merge desired branch into current branch git branch -d [branch] # delete merged branch (close a branch) git branch -D [branch] # Terminate with extreme prejudice
Remote Branch
git checkout master git branch mybranch # note: does not auto checkout the new branch! git checkout mybranch
# ... make changes ...
git push --set-upstream origin mybranch
# git push <remote_name> --delete <branch_name> git push origin --delete mybranch
ref: [7]
List Remote Branches
List only remote branches fetched locally:
git branch -r
To fetch a list of all remote branches:
git fetch --all # I believe this equivalent to: git remote update
To update all locally fetched remote branches:
git pull --all
merge
Merge branches:
git merge [branch] # merge [branch] into current branch
Merge 'test' branch back into master:
git checkout master git merge 'test'
To close (delete) the merged branch:
git branch -d 'test'
Squash Merge
Squash Merge: [1]
git checkout master git merge --squash bugfix git commit
Diverged Branches
repo# git pull From github.com:myrepo * branch releases/myrepo -> FETCH_HEAD hint: You have divergent branches and need to specify how to reconcile them. hint: You can do so by running one of the following commands sometime before hint: your next pull: hint: hint: git config pull.rebase false # merge (the default strategy) hint: git config pull.rebase true # rebase hint: git config pull.ff only # fast-forward only hint: hint: You can replace "git config" with "git config --global" to set a default hint: preference for all repositories. You can also pass --rebase, --no-rebase, hint: or --ff-only on the command line to override the configured default per hint: invocation. fatal: Need to specify how to reconcile divergent branches.
I prefer rebase.true
Merge Conflict
Abort Merge
git merge --abort git reset --hard git reset --soft HEAD~
pull
Merge clones and pull from remote:
git pull [repo] [branch] # pull changes from another clone
Dry run:
git pull --dry-run
To try a pull without staving:
git pull --no-commit git reset --merge
Dry run: [8]
git fetch origin && git merge origin/master --no-commit --no-ff && git reset --merge
After a dirty pull merge to clean up log:
git rebase origin/master
Remotes
Working with Remotes:
git fetch [repo] [branch] # pull change info only (safe) git log -p HEAD..FETCH_HEAD # review changes git remote add [RemoteName] [RemoteRepoURL] # add remote repo git remote -v # list remote repos git branch -r # list remote repos branches git fetch [rrepo] # pull changes info git log -p [branch]..[rrepo]/[branch] # see changes to remote repo compared to local git merge [rrepo]/[branch] # merge remote branch to local git pull . remotes/[rrepo]/[branch] # alternate form of merge git pull # can pull changes directly if is clone git config --get remote.origin.url # see what original clone was (origin) git push origin master
Change remote url: [9]
git remote set-url origin ssh://git@gitserver/git/path
Git Hub
~/.gitconfig:
[user] name = Kilo Force email = kiloforce@oeey.com
Initial setup:
mkdir gittest cd gittest git init . touch README.TXT git add README.TXT git commit -m 'initial commit' git remote add origin https://bitbucket.org/kiloforce/gittest git push origin master
git clone https://bitbucket.org/kiloforce/gittest git add file.txt git commit -a -m 'file commit' git push
Tags
git tag # list tags git tag -l # list tags git tag -l <pattern> # list tags matching pattern git log --decorate # list tags in log git tag [tag] # tag current position git log master..[tag] # show logs from master to tag git log [tag]..master # show logs from tag to master (rev) git checkout [tag] # update to certain tag git describe # show the current tag
Sync tags: [10]
git fetch -p -P
# or git fetch --prune --prune-tags # or git fetch -p -P origin # or git fetch --prune --prune-tags origin
# FORCE [rejected] ... (would clobber existing tag) git fetch -p -P -f origin
git fetch [<options>] [<repository> # -p, --prune # -P, --prune-tags # -f, --force
Force Sync Tags
If you get a "would clobber existing tag", you can delete and force: [11]
git tag -l | xargs git tag -d git fetch --tags
clean
Show what will be deleted:
git clean -n
To Clean:
git clean -f
Remove directories:
git clean -fd
Remove ignored files:
git clean -fX
Remove ignored and non-ignored files:
git clean -fx
Ref: [12]
reset
DON'T TRY THIS ON ONE FILE!
Reset whole tree: (revert changes) [13]
# won't touch new files git reset --hard HEAD^ # reset to head (does not rm new files) git reset --hard HEAD # return the entire working tree to the last committed state
Reset to changeset (similar to checkout):
git reset --hard <HASH>
Throw away local changes:
git reset --hard origin/[BRANCH]
Soft, Mixed, Hard:
- Soft - undo commit, but keep index
- Mixed - undo commit, and undo index, but keep working directory ** DEFAULT **
- Hard - reset commit, reset index and reset working directory
ref: [14]
Reset Hard with Prejudice
git clean -xdf && git reset --hard HEAD
Drop local commits
git reset --hard origin/master
revert like
re-checkout all files, overwriting any local changes. This is most similar to "svn revert" if you're used to Subversion commands:
git checkout .
Reset on file:
git checkout -- hello.rb git checkout HEAD hello.rb
rollback like
rollback or undo the last commit [15]
git reset --soft HEAD~
git commit -m "Something terribly misguided" git reset --soft HEAD~ << edit files as necessary >> git add ... #git commit -c ORIG_HEAD #git commit -a -m "Something right"
Or with prejudice:
git reset --hard HEAD
Stash
Stash changes
git stash git stash save "message"
Apply last change without deleting:
git stash apply
Apply last change with deleting:
git stash pop
Delete last stash:
git stash drop git stash drop stash@{1} # drop stash 1
List stashes:
git stash
Show files in last stash:
git show
Amend
(similar to annotate / amend commit message)
Changing a commit message, and/or files [16]
git commit --amend
Change author:
git commit --amend --author="Author Name <email@address.com>"
Changing an older commit with rebase: [17]
git rebase -i [change_set_prior_to_target] # change "pick" for target changesets git commit --amend --author="Author Name <email@address.com>" git rebase --continue
# or git commit --amend --reset-author --no-edit
Cherry Pick
git cherry-pick [hash]
Cherry Pick a range: [2]
git cherry-pick [hash]^...[hash]
Cherry Pick From Anther Repository
Cherry Pick From Anther Repository [3]
git remote add other https://example.link/repository.git git fetch other # or git fetch other BRANCH git cherry-pick first_commit...last_commit ... # when done: git remote remove other
Submodules
git submodule init git submodule sync git submodule update # or git submodule update --init --recursive
Show submodule commit versions and branches:
git submodule status
Installation
Manual Installation
Remove existing:
yum remove git apt-get remove git
Install dependencies:
yum -y install gcc make curl-devel openssl-devel expat-devel autoconf gettext # ? perl-ExtUtils-MakeMaker sudo apt-get install curl libcurl4-openssl-dev libexpat1-dev gettext zlib1g-dev autoconf suod apt-get install tclsh # is this needed?
Visit here to determine the version you want:
https://git-scm.com/download/linux # it will say "The latest version is "2.45.1" (as of 14-May-2024)
# or manually find in the list: http://kernel.org/pub/software/scm/git
Download Git source:
# GIT_VER=1.7.8.3 # removed # GIT_VER=1.8.2.3 # 09-May-2013 earliest 1.x still available # GIT_VER=1.8.3.4 # 22-Jul-2013 # GIT_VER=2.6.3 # 05-Nov-2015 # GIT_VER=2.25.1 # 17-Feb-2020 # GIT_VER=2.44.0 # 23-Feb-2024 GIT_VER=2.45.1 # 14-May-2024 mkdir -p ~/.src ; cd ~/.src # wget http://git-core.googlecode.com/files/git-$GIT_VER.tar.gz wget http://kernel.org/pub/software/scm/git/git-$GIT_VER.tar.gz tar -zvxf git-$GIT_VER.tar.gz cd git-$GIT_VER
Configure install:
make configure # ./configure --prefix=/opt/git ./configure make clean make all sudo make install
Git man pages: (optional step)
mkdir -p ~/.src ; cd ~/.src # wget http://git-core.googlecode.com/files/git-manpages-$GIT_VER.tar.gz wget http://kernel.org/pub/software/scm/git/git-manpages-$GIT_VER.tar.gz sudo tar -zvxf git-manpages-$GIT_VER.tar.gz -C /opt/git/share/man/
Paths: /etc/bashrc
export PATH=/opt/git/bin:$PATH export MANPATH=/opt/git/share/man/:$MANPATH echo -e "\n\nexport PATH=/opt/git/bin:\$PATH\n" >> ~/.bash_profile echo -e "\n\nexport MANPATH=/opt/git/share/man/:\$MANPATH\n" >> ~/.bash_profile
Note: the NO_GETTEXT=1 is needed to avoid a "Makefile:252: po/bg.msg] Error 127" [4]
Other Installation Options
Manually install man pages:
# dependencies: (need RPMforge) # yum install asciidoc libxslt xmlto make man sudo make install-man
/etc/bashrc: export PATH=/opt/git/bin:$PATH export MANPATH=/opt/git/share/man/
# direct usage man -M ~/share/man git-commit # or export MANPATH=~/share/man man git-commit
Personal install: (non configure method)
# personal install ~/bin ~/lib ~/share ... (prefix=~): make make install
Global install: (non configure method)
$ make prefix=/usr/local all doc info sudo make prefix=/usr/local install install-doc install-html install-info
Installation with DAG
Install with DAG:
# http://dag.wieers.com/rpm/packages/git/git-1.5.2.1-1.el5.rf.i386.rpm rpm -Uvh http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm yum install rpmforge-release # update rpmforge yum install git
FreeBSD Installation
pkg_add -r git
Installation OF LFS
# git clone git@github.com:git-lfs/git-lfs.git
wget https://github.com/git-lfs/git-lfs/releases/download/v3.5.1/git-lfs-linux-amd64-v3.5.1.tar.gz tar -zvxf git-lfs-linux-amd64-v3.5.1.tar.gz sudo cp git-lfs-3.5.1/git-lfs /opt/git/bin/
Use alternative ssh key
export GIT_SSH_COMMAND="ssh -i /path/to/git-private-access-key" git clone REPO
or
GIT_SSH_COMMAND="ssh -i /path/to/git-private-access-key" git clone REPO
or
git clone -c "core.sshCommand=ssh -i ~/.ssh/<key>" git@github.com:<user>/<repo>.git
or wrapper:
~/.gitwrap.sh:
#!/bin/bash ssh -i ~/.ssh/gitkey_rsa "$@"
export GIT_SSH=~/gitwrap.sh
or per repo config:
vim .git/config
[core] sshCommand = ssh -i <IDENTITY_KEY_LOCATION> -o IdentitiesOnly=yes
ref: bash - How to specify the private SSH-key to use when executing shell command on Git? - Stack Overflow - https://stackoverflow.com/questions/4565700/how-to-specify-the-private-ssh-key-to-use-when-executing-shell-command-on-git
Create Central Repo
Create a shared bare repo:
## Set permission umask 0002 mkdir git chown :sharedgroup git # chmod g+ws git chmod g+s git cd git
# git init --bare some_project.git # git clone --mirror some_existing_project.git # git init --bare --shared some_project.git mkdir some_project.git ; cd some_project.git git init --bare --shared .
## Fix permissions and ownership # chown some_project.git :sharedgroup -R # find some_project.git -type d -exec chmod g+ws {} \;
# config - with shared setting [core] repositoryformatversion = 0 filemode = true bare = true sharedrepository = 1 [receive] denyNonFastforwards = true
Central Repo
git clone [workingrepo] [dir] --mirror # create bare repo (ie dir='central')
## Make group editable: find test-git.git -type d -exec chmod g+s {} \; chmod g+w test-git.git -R chown :git -R test-git.git/
git clone [repo] # clone bare repo ... make changes and commit ... git push # push changes to repo
git clone kenneth@git.oeey.com:/git/oeey-git.git oeey-git.git --mirror
Mirror Repo
Create local mirror:
git clone [URL] [dir] --mirror cd [dir] git update-server-info # DON'T FORGET THIS STEP!
Sync Mirror
git remote update
cron job:
# 1 AM Sync git mirror 0 1 * * * /usr/bin/git --git-dir=/git/some_git_repo.git remote update
Set Mirror Default Branch
Option #1 - hack HEAD directly
/HEAD ref: refs/heads/main_branch
Option #2 - use symbolic-ref:
git symbolic-ref HEAD refs/heads/main_branch
ref:
- Set the default branch in a Git repository (Example) - https://coderwall.com/p/wmizjg/set-the-default-branch-in-a-git-repository
- Git: Correct way to change Active Branch in a bare repository? - Stack Overflow - https://stackoverflow.com/questions/3301956/git-correct-way-to-change-active-branch-in-a-bare-repository
Migrate Repo
mkdir new_repo cd new_repo git init . cd ../old_repo git remote add origin [path]/new_repo # or url # or manually modify .git/config to point to new repo git push origin master
Git add is different
"Many revision control systems provide an add command that tells the system to start tracking changes to a new file. Git's add command does something simpler and more powerful: git add is used both for new and newly modified files, and in both cases it takes a snapshot of the given files and stages that content in the index, ready for inclusion in the next commit." [18]
cheat git
Git Cheat Sheet - Guides - GitHub
forking
http://phonegap.pbworks.com/Git%3A-Forking-PhoneGap%C2%A0Documentation
http://programblings.com/2008/07/21/setting-up-a-long-term-fork-with-git/
Help.GitHub - Forking a project - http://help.github.com/forking/
#Fork in GitHub # setup git clone git@github.com:billyanyteen/github-services.git cd github-services git remote add upstream git://github.com/pjhyett/github-services.git git fetch upstream # push changes git push origin master # pull changes #git fetch upstream #git merge upstream/master git pull upstream master
- Git forking for fun and profit /by @assaf - http://labnotes.org/2008/04/30/git-forking-for-fun-and-profit/
- Setting up a long term fork with Git » Programblings - http://programblings.com/2008/07/21/setting-up-a-long-term-fork-with-git/
- Help.GitHub - Sending pull requests - http://help.github.com/pull-requests/
Files
git-rm
git-rm - Remove files from the working tree and from the index - http://www.kernel.org/pub/software/scm/git/docs/git-rm.html
git-mv
git-mv - Move or rename a file, a directory, or a symlink - http://www.kernel.org/pub/software/scm/git/docs/git-mv.html
Log
Committed history:
git log
Pretty one line logs: (last 3 logs)
git log --pretty=oneline -3
Diff
Diff of dirty, tracked files in the tree to the content added to the index:
git diff
Diff between index and HEAD of the current branch -- i.e. the changes that will be committed on git commit:
git diff --cached
Patch
Create patch:
git diff --no-prefix origin/master/HEAD > my_bugNNN.patch
Creating the patch: [19]
git format-patch [remote]/master --stdout > fix_empty_poster.patch
What changes in patch:
git apply --stat fix_empty_poster.patch
Test patch before applying (for conflicting files):
git apply --check fix_empty_poster.patch
Apply patch:
git apply fix_empty_poster.patch
Apply and signoff patch: (alternate to apply patch with signoff)
git am --signoff
Branches
List branches: (* indicates current)
git branch # list local branches git branch -r # list remote branches git branch -a # list remote and local branches git branch -v # list local branches and source
Create branch:
git branch [BRANCH] # local branch of current point in history: git push origin origin:refs/heads/[BRANCH] # remote empty branch
List origin of current checkout branch: (also lists remote branches)
git ls-remote
Checkout branch:
git checkout [BRANCH] # checkout branch git checkout [REMOTE]/[BRANCH] git checkout [LOCALNAME] [REMOTE]/[BRANCH] git checkout -b [BRANCH] # create and checkout branch git checkout --track -b [BRANCH] # create and set push to use upstream (if not default)
Delete branch:
git branch -d [BRANCH] # delete merged branch (close branch) git branch -D [BRANCH] # delete non merged branch - destructive git push origin :[BRANCH] # delete remote branch git push origin :heads/[BRANCH] # delete remote branch (not sure difference from previous)
Create/Push remote branch:
git push [REMOTE] [BRANCH] git push origin [BRANCH] git push [REMOTE] [LOCALBRANCH]:[BRANCH] git push origin origin:refs/heads/[BRANCH] # remote empty branch
Merge (See #Merging)
git merge [BRANCH] # merge branch into current
Determine branch of a detached head: [20]
git describe --contains --all HEAD git log -n 1 --pretty=%d HEAD git show -s --pretty=%d HEAD git branch --contains HEAD # not best
Automate creating remote branches: [21]
#!/bin/sh # git-create-branch <branch_name> if [ $# -ne 1 ]; then echo 1>&2 Usage: $0 branch_name exit 127 fi set branch_name = $1 git push origin origin:refs/heads/${branch_name} git fetch origin git checkout --track -b ${branch_name} origin/${branch_name} git pull
Compare Branches
Show diff
git diff branch1..branch2 git diff branch2.. # compare to current branch git diff branch1...branch2 # only with changes in one but not both with 3 dots (mutually exclusive)
Show only files changed:
git diff --name-only branch1..branch2 # with status change: git diff --name-status branch1..branch2 # file with more status details: git diff --stat branch2..
eg. diff --name-status M somefile/file1
Show commits between branches
git cherry branch2 # and current branch git cherry branch1 branch2 git cherry -v branch2 # commit and commit title
eg. cherry -v + 95aaeac2f9e446018479bd00fc280ab217xxxxxx some title1 + 4854da061b80a902b0d2ca0ac367c53d47xxxxxx some title2
Show log between branches:
git log branch1..branch2 git log branch1...branch2 # show commits either but not both with 3 dots (mutually exclusive) git log branch2.. # compare to current branch
-- others --
Pretty visual output (glog style): [5]
git log --left-right --graph --cherry-pick --oneline branch1..branch2 git log --left-right --graph --cherry-pick --oneline branch2..
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset' --abbrev-commit --date=relative master..branch-X
git log --oneline --graph --all --decorate --abbrev-commit git log --oneline --graph --all --decorate --abbrev-commit branch2..
git log --all --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset'
git log --oneline --graph --all --decorate # --oneline is short for --pretty=oneline --abbrev-commit
# commits in develop that are not in master: git log --oneline --no-merges origin/master..origin/develop
# show files which ones are modified (not glog style) git diff --stat --no-merges origin/master..origin/develop
# show commits about to be merged # HEAD is more convenient to use than branch name git fetch git log --oneline --no-merges origin/master..HEAD
Make Two Branches Identical
Fake "theirs strategy":
if you want DOWNSTREAM to reflect exactly what UPSTREAM is:
git switch -c tmp UPSTREAM git merge -s ours DOWNSTREAM # ignoring all changes from main git switch DOWNSTREAM git merge tmp # fast-forward to tmp HEAD, which is dev git branch -D tmp # deleting tmp
This has the benefit of recording the upstream ancestor as the first parent, so that the merge means "absorb this out-of-date topic branch" rather than "destroy this topic branch and replace it with upstream".
ref: github - git command for making one branch like another - Stack Overflow https://stackoverflow.com/questions/4911794/git-command-for-making-one-branch-like-another/4912267#4912267
---
The three main ways to do this:
1. Don't bother. Abandon branch A, make a new A2, and use that.
2. Use git reset or equivalent to re-point A elsewhere.
Methods 1 and 2 are effectively the same in the long run. For instance, suppose you start by abandoning A. Everyone develops on A2 instead for a while. Then, once everyone is using A2, you delete the name A entirely. Now that A is gone, you can even rename A2 to A (everyone else using it will have to do the same rename, of course). At this point, what, if anything, looks different between the case where you used method 1 and the case where you used method 2? (There is one place you may still be able to see a difference, depending on how long your "long run" is and when you expire old reflogs.)
3. Make a merge, using a special strategy (see "alternative merge strategies" below). What you want here is -s theirs, but it doesn't exist and you must fake it.
git - Making two branches identical - Stack Overflow - https://stackoverflow.com/questions/36320517/making-two-branches-identical
Tags
Create tag:
git tag [TAG] git tag -a [TAG] # with message using editor git tag -a [TAG] -m 'message' # with message
List tags:
git tag git tag -l [PATTERN] git show [TAG] # show tag details and messages
Delete tag:
git tag -d [TAG]
Push tags to remote:
git push --tags
Get tags from remote:
git fetch
git describe git describe --always --tag git log --pretty=format:'%ad %h %d' --abbrev-commit --date=short -1 git log --no-walk --tags --pretty="%D-g%h %s" # show all base tags (for 'git describe')
Remotes
git-remote - manage set of tracked repositories - http://www.kernel.org/pub/software/scm/git/docs/git-remote.html
Remote Git repository tracking
Help:
man git-remote git help remote
Add remote:
git remote add test git://github.com/user/test.git # add and fetch remote details git remote add test git://github.com/user/test.git -f
List remotes:
git remote git remote show
Remote details:
git remote -v git remote show [REMOTE] git remote show origin
List origin of current checkout branch:
git ls-remote
Remove remote:
git remote rm [REMOTE]
Rename remote:
git remote rename [REMOTE]
Resources:
- Help.GitHub - Working with remotes - http://help.github.com/remotes/
git-fetch
Download objects and refs from another repository - http://www.kernel.org/pub/software/scm/git/docs/git-fetch.html
Fetch remote details:
git fetch -v git fetch [REMOTE]
Checkout new branch from remote:
git checkout -b [LOCALNAME] [REMOTE]/[BRANCH]
git-pull
git-pull - Fetch from and merge with another repository or a local branch - http://www.kernel.org/pub/software/scm/git/docs/git-pull.html
Pull changes:
# Pull changes (git fetch followed by git merge) # defaults to current branch from remote git pull git pull [remote_name]/[branch] git pull origin master git pull --dry-run # don't actually do anything
You asked me to pull without telling me which branch you want to merge with, and 'branch.bob.merge' in your configuration file does not tell me, either. Please specify which branch you want to use on the command line and try again (e.g. 'git pull <repository> <refspec>'). See git-pull(1) for details. If you often merge with the same branch, you may want to use something like the following in your configuration file: [branch "bob"] remote = <nickname> merge = <remote-ref> [remote "<nickname>"] url = <url> fetch = <refspec> See git-config(1) for details.
git-push
NOTE: only can push changes when the 'master' branch is checked out. Other branches do not appear to work.
git-push - Update remote refs along with associated objects - http://www.kernel.org/pub/software/scm/git/docs/git-push.html
Dry run:
git push --dry-run [...]
Push changes:
# defaults to current branch from remote git push git push remote_name my_branch:remote_branch
git push REMOTENAME BRANCHNAME git push REMOTENAME LOCALBRANCHNAME:REMOTEBRANCHNAME
NOTE: One important thing is that you should push only to remote branches that are not currently checked out on the other side (for the same reasons you never switch to a remote branch locally)! Otherwise the working copy at the remote branch will get out of date and confusion will ensue.
Create/Push remote branch:
git push [REMOTE] [BRANCH] git push [REMOTE] [LOCALBRANCH]:[BRANCH]
$ git push [24] master:master $ git push [25] master $ git push [public-repo] master You may force git push to perform the update anyway by preceding the branch name with a plus sign: $ git push ssh://yourserver.com/~you/proj.git +master
To git@github.com:user/repo.git ! [rejected] master -> master (non-fast-forward) error: failed to push some refs to 'git@github.com:user/repo.git' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (e.g. 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.
git pull git push -f
Failure of branch to push: http://ken-blog.krugler.org/2010/02/25/git-failed-to-push-some-refs-the-multiple-branch-variant/
Push tag: [26]
git push REMOTENAME TAGNAME # push all tags git push REMOTENAME BRANCHNAME --tags
Delete tag:
# You are literally telling git “push nothing into BRANCHNAME on REMOTENAME” git push REMOTENAME :BRANCHNAME
change remote
"Changing a remote’s URL - There is no direct command to change a remote’s URL, so you will usually run git remote rm followed by git remote add to change a URL. You can also edit the repo’s .git/config file directly to change the URL without re-fetching the remote." [27]
git remote rm [REMOTE] git remote add [REMOTE]
Rebase
To fetch new items from the git mirror, just do
git fetch
Then, you'll need to merge your changes with those in the head. Two options: rebase or merge.
If you haven't published your changes, you can just use rebase:
# git rebase [BRANCH]git rebase master
git rebase origin/master
If there are conflicts, it will ask you to resolve them. After all is done, your commits will lie on top of those in git. Note that if one of your commits exactly matches changes made in git, it will silently disappear in rebasing.
An alternative is merging, which does not rewrite history,
# git merge [BRANCH] git merge master
References:
- Staying abreast SVN - http://projects.scipy.org/numpy/wiki/GitMirror
Merging
Merge branch into current branch
git merge [BRANCH]
Don't auto commit merge:
git merge [BRANCH] --no-commit
Git TUI merge tool:
git mergetool
Git User’s Manual - Resolving a merge - http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#resolving-a-merge
Show changes to a conflicting file:
git diff [FILE]
During the merge, the index holds three versions of each file. Each of these three "file stages" represents a different version of the file:
$ git show :1:file.txt # the file in a common ancestor of both branches $ git show :2:file.txt # the version from HEAD. $ git show :3:file.txt # the version from MERGE_HEAD.
# common base version of the file git show :1:some_file.cpp # 'ours' version of the file git show :2:some_file.cpp # 'theirs' version of the file git show :3:some_file.cpp
Some special diff options allow diffing the working directory against any of these stages:
$ git diff -1 file.txt # diff against stage 1 $ git diff --base file.txt # same as the above $ git diff -2 file.txt # diff against stage 2 $ git diff --ours file.txt # same as the above $ git diff -3 file.txt # diff against stage 3 $ git diff --theirs file.txt # same as the above.
If you get stuck and decide to just give up and throw the whole mess away, you can always return to the pre-merge state with
$ git reset --hard HEAD
Or, if you’ve already committed the merge that you want to throw away,
$ git reset --hard ORIG_HEAD
git merge [rrepo]/[branch] # merge remote branch to local git pull . remotes/[rrepo]/[branch] # alternate form of merge
vimdiff
vimdiff:
vimdiff [options] file1 file2
ctrl+w ctrl+w - switch windows do - diff obtain change (do below missing) dp - diff push changes [c - previous difference ]c - next difference :diffupdate - diff update ;) :syntax off - syntax off zo - open folded text zc - close folded text
Change Commit Message
Change last commit message with:
git commit --amend git commit --amend -m "some message"
Compress Repository
Ensuring good performance - http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#ensuring-good-performance
On large repositories, git depends on compression to keep the history information from taking up too much space on disk or in memory.
This compression is not performed automatically. Therefore you should occasionally run git-gc(1):
$ git gc
to recompress the archive. This can be very time-consuming, so you may prefer to run git gc when you are not doing other work.
Ignore
gitignore - Specifies intentionally untracked files to ignore - http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
Patterns read from a .gitignore file in the same directory as the path, or in any parent directory, with patterns in the higher level files (up to the toplevel of the work tree) being overridden by those in lower level files down to the directory containing the file
Patterns read from $GIT_DIR/info/exclude
$ cat Documentation/.gitignore # ignore generated html files, *.html # except foo.html which is maintained by hand !foo.html
Archive (Export)
git-commit - Record changes to the repository
Help:
man git-archive git help archive
SVN calls this export, Git calls this archive.
Simple method:
- git clone followed by removing the .git repository directory.
Export project:
git archive master | tar -x -C /somewhere/else
Export and compress:
git archive master | bzip2 >source-tree.tar.bz2
Zip archive:
git archive --format zip --output /full/path master
Prefix folder in zip:
git archive --format zip --output /path/to/file.zip --prefix=newdir/ master
Uncompressed archive (-0 for uncompressed)
git archive --format zip --output "output.zip" master -0
Archive latest:
git archive -o latest.zip HEAD
git export:
git checkout-index -a -f --prefix=/destination/path/ git checkout-index --prefix=git-export-dir/ -a
with remote:
git-archive --format=tar --remote=ssh://remote_server/remote_repository master | tar -xf -
other: [28]
git archive HEAD | (cd ~/path/where/I/want/it/ && tar -xvf -) rsync path/I/want/to/export/ -ri --del -m --exclude ".*" ~/path/where/I/want/it/ |grep sT
other 2: [29]
git archive master | gzip > latest.tgz git archive master | bzip2 > latest.tar.bz2
Resources:
- How to do a "git export" (like "svn export") - Stack Overflow - http://stackoverflow.com/questions/160608/how-to-do-a-git-export-like-svn-export
Git Server
How to set up your own private Git server on Linux | Bradley Wright (using SSH)
?? (using git-daemon)
man git-daemon
yum install git-daemon
Destructive Operations
Rewrite Commit Authors
List authors:
git log --all --format='%aN <%aE> - %cN <%cE>' | sort -u
Redo all commits:
for i in 1 2 ; do git filter-branch -f --tag-name-filter cat --commit-filter ' GIT_AUTHOR_NAME="Admin"; GIT_AUTHOR_EMAIL="admin@t0e.org"; GIT_COMMITTER_NAME="Admin"; GIT_COMMITTER_EMAIL="admin@t0e.org"; git commit-tree "$@"' -- --all done
Note: will need a '-f' to overwrite backup if you ever run a second time.
Rewrite certain commits:
for i in 1 2 ; do git filter-branch --tag-name-filter cat --commit-filter ' if [ "$GIT_AUTHOR_NAME" = "Ryan" -o "$GIT_AUTHOR_NAME" = "Ryan Test" ]; then GIT_AUTHOR_NAME="Ryan Test"; GIT_AUTHOR_EMAIL="rtest@oeey.com"; GIT_COMMITTER_NAME="Ryan Test"; GIT_COMMITTER_EMAIL="rtest@oeey.com"; elif [ "$GIT_AUTHOR_NAME" = "Mike Test" ]; then GIT_AUTHOR_NAME="Mike Test"; GIT_AUTHOR_EMAIL="mtest@oeey.com"; fi; git commit-tree "$@"' -- --all done
Fancier filter [30]
#!/bin/sh git filter-branch --env-filter ' n=$GIT_AUTHOR_NAME m=$GIT_AUTHOR_EMAIL case ${GIT_AUTHOR_NAME} in user1) n="User One" ; m="user1@example.com" ;; "User Two") n="User Two" ; m="user2@example.com" ;; esac export GIT_AUTHOR_NAME="$n" export GIT_AUTHOR_EMAIL="$m" export GIT_COMMITTER_NAME="$n" export GIT_COMMITTER_EMAIL="$m" '
GitHub
SSH: git@github.com:kiloforce/test.git HTTP: https://kiloforce@github.com/kiloforce/test.git Git Read-Only: git://github.com/kiloforce/test.git
Global setup:
Download and install Git git config --global user.name "Kilo Force" git config --global user.email kiloforce@oeey.com
Next steps:
mkdir test cd test git init touch README git add README git commit -m 'first commit' git remote add origin git@github.com:kiloforce/test.git git push origin master
Existing Git Repo?
cd existing_git_repo git remote add origin git@github.com:kiloforce/test.git git push origin master
Importing a Subversion Repo:
https://github.com/kiloforce/test/imports/new
When you're done:
https://github.com/kiloforce/test
Check out project:
git clone git@github.com:kiloforce/test.git test ( modify files ) git commit -a -m 'changes' git push # git push git@github.com:kiloforce/test.git
NOTE: don't check out from https://github.com/kiloforce/test or you will get this error:
fatal: remote error: You can't push to git://github.com/kiloforce/test.git Use git@github.com:kiloforce/test.git
SVN for GitHub
Ever wanted to use SVN to grab code from GitHub? Well, now you can, and just like that GitHub is the world's biggest Subversion host. Here's a few things you might like to do with it:
- Use any GitHub repository as an SVN external.
- Use TortoiseSVN or your favorite SVN tool to view Git repositories.
- Use existing build tools or continuous integrations systems that only work with SVN.
Check out projects through svn.github.com: (http or https)
svn checkout https://svn.github.com/kiloforce/test.git test
Notice, on checkout there will be the following error that can be ignored.
REPORT of '/kiloforce/test.git/!svn/vcc/default': 200 OK (https://svn.github.com)
References:
- Announcing SVN Support - GitHub - http://github.com/blog/626-announcing-svn-support
- Subversion Write Support - GitHub - https://github.com/blog/644-subversion-write-support
Caching Password
authentication - Git push requires username and password - Stack Overflow - http://stackoverflow.com/questions/6565357/git-push-requires-username-and-password
The following command will save your password in memory for sometime. (For git 1.7.10 or newer.)
# Set git to use the credential memory cache $ git config --global credential.helper cache
# Set the cache to timeout after 1 hour (setting is in seconds) $ git config --global credential.helper 'cache --timeout=3600'
You can also add to your git config (in repo or common), to remember which user name:
[credential "https://example.com"] username = kiloforce
Credential Store
~/.git-credentials
git config credential.helper 'store <options>'
ref: https://git-scm.com/docs/git-credential-store
Notch anti Git
- Oh, and I’ve finally committed the Music Blocks to the repository.
- (Oh, wait, no, I didn’t.. Doing so broke git, so we’re changing to svn because git is horrible and evil)
-- Notch (Jan 06, 2011)
Source: http://notch.tumblr.com/post/2623477410/strategy-meeting-day-results
Git vs the World
Why Git is Better Than X - http://whygitisbetterthanx.com/
Git Quick Start
Cloning and Creating a Patch:
$ git clone git://github.com/git/hello-world.git $ cd hello-world $ (edit files) $ git add (files) $ git commit -m 'Explain what I changed' $ git format-patch origin/master
Creating and Commiting:
$ cd (project-directory) $ git init $ (add some files) $ git add . $ git commit -m 'Initial commit'
Documentation
Git User's Manual (for version 1.5.3 or newer)
Ports
Git uses port 9418:
git clone git://git.kernel.org/pub/scm/git/git.git
If you have problems connecting (Git uses port 9418), you can try to access the repository over the HTTP protocol:
git clone http://www.kernel.org/pub/scm/git/git.git
Git vs SVN
Git | SVN |
---|---|
git clone url | svn checkout url |
git pull | svn update |
Git Turotials
Download
This includes links for binaries and source code.
gerrit - code review
gerrit - Gerrit Code Review - Google Project Hosting - http://code.google.com/p/gerrit/
Web based code review and project management for Git based projects.
Gerrit is a web based code review system, facilitating online code reviews for projects using the Git version control system.
Gerrit makes reviews easier by showing changes in a side-by-side display, and allowing inline comments to be added by any reviewer.
Gerrit simplifies Git based project maintainership by permitting any authorized user to submit changes to the master Git repository, rather than requiring all approved changes to be merged in by hand by the project maintainer. This functionality enables a more centralized usage of Git. Resources
ssh config
~/.ssh/config
Host myserver user bob Host * user jenkins
Host gh-foo Hostname github.com User git IdentityFile ~/.ssh/foo_github_id Host gh-bar Hostname github.com User git IdentityFile ~/.ssh/bar_github_id
Specify SSH Key from Command Line
GIT_SSH_COMMAND="ssh -i /path/to/id_rsa" git clone ssh://git@git.server.com/path/repo
Create Empty Branch
November 2021 Update: As of git version 2.27, you can now use git switch --orphan <new branch> to create an empty branch with no history.
git switch --orphan <new branch> git commit --allow-empty -m "Initial commit on orphan branch" git push -u origin <new branch>
Original solution:
git checkout --orphan empty-branch git rm -rf . git commit --allow-empty -m "root commit" git push origin empty-branch
ref: [31]
--
Use option --orphan to create branch with no parents.
git checkout --orphan new-empty-branch git rm -rf . git commit --allow-empty -m "Initial commit on orphan branch"
ref: [32]
Sign Commit
Create GPG key, and set gpgsign = true
Sign all commits with gpgsign:
git config --global commit.gpgsign true
~/.gitconfig :
[commit] gpgsign = true
Sign single commit:
git commit -S git commit --gpg-sign
generate GPG keys
gpg --full-generate-key
Show siged commits
git log --show-signature
Mercurial
Git for Mercurial users
Command equivalence table - http://mercurial.selenic.com/wiki/GitConcepts#Command_equivalence_table
Git vs Mercurial - WikiVS - http://www.wikivs.com/wiki/Git_vs_Mercurial
See Git vs Mercurial
Convert Git to Mercurial
Really easy!
hg convert [git_repo] [hg_repo]
Convert Mercurial to Git
cd ~ git clone git://repo.or.cz/fast-export.git git init git_repo cd git_repo ~/fast-export/hg-fast-export.sh -r /path/to/old/mercurial_repo git checkout HEAD
Source: Convert Mercurial project to Git - Stack Overflow - http://stackoverflow.com/questions/16037787/convert-mercurial-project-to-git
hg id
git rev-parse HEAD
# git rev-parse HEAD ecf4fb28be83f2f1fcfe56b7311ee3477ab742c2
incoming and outgoing
[alias] out = log --pretty=oneline --abbrev-commit --graph @{u}.. outgoing = log --pretty=oneline --abbrev-commit --graph @{u}.. in = !git fetch && git log --pretty=oneline --abbrev-commit --graph ..@{u} incoming = !git fetch && git log --pretty=oneline --abbrev-commit --graph ..@{u}
Note: run "git fetch" first
Reference:
- Coderwall | git outgoing/incoming changes - https://coderwall.com/p/fowimq/git-outgoing-incoming-changes
---
Mimic 'hg incoming' and 'hg outgoing'
hg incoming:
git log ..@{u}
hg outgoing:
git log @{u}..
git config --global alias.incoming '!git remote update -p; git log ..@{u}' git config --global alias.outgoing 'log @{u}..'
[alias] incoming = "!git remote update -p; git log ..@{u}" outgoing = log @{u}..
Reference: mercurial - Using Git how do I find changes between local and remote - Stack Overflow - http://stackoverflow.com/questions/231211/using-git-how-do-i-find-changes-between-local-and-remote
Issues
Unable to find http helper
Issue:
$ git clone git://github.com/git/hello-world.git fatal: Unable to find remote helper for 'http'
Solution:
- The curl library was missing when git was compiled
- Install curl-devel and recompile.
Connection Refused
Issue:
$ git clone git://github.com/git/hello-world.git Initialized empty Git repository in /data/store/home/kenneth/git-1.7.1/hello-world/.git/ github.com[0: 207.97.227.239]: errno=Connection refused fatal: unable to connect a socket (Connection refused)
Solution:
- Open outbound TCP port 9418 on the Firewall
bash: git-upload-pack: command not found
$ git clone username@host:~/project/path/contactdb Initialized empty Git repository in c:/Documents and Settings/Administrator/My Documents/projects/contactdb/.git/ bash: git-upload-pack: command not found fatal: The remote end hung up unexpectedly
Why is this git clone command failing? - Stack Overflow - http://stackoverflow.com/questions/999195/why-is-this-git-clone-command-failing
test with:
ssh [server] git-upload-pack
Solution:
- If this fails, add the path to the program to the user's .bashrc on the remote server
insufficient permission
Error:
error: insufficient permission for adding an object to repository database ./objects
Fix:
sudo chown -R git:git repo.git/
sudo chmod -R gituser.gituser objects
git - Error pushing to GitHub - insufficient permission for adding an object to repository database - Stack Overflow - http://stackoverflow.com/questions/1918524/error-pushing-to-github-insufficient-permission-for-adding-an-object-to-reposit
ssl certificate verify failed
Error:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
Ignore ssl certificate verification: [33]
export GIT_SSL_NO_VERIFY=true # or git config --global http.sslverify false
git clone https://github...
References:
- server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none - Stack Overflow http://stackoverflow.com/questions/21181231/server-certificate-verification-failed-cafile-etc-ssl-certs-ca-certificates-c
insufficient permission for adding an object to repository database ./objects
$ git push origin master ... error: insufficient permission for adding an object to repository database ./objects fatal: failed to write object error: unpack failed: unpack-objects abnormal exit
See shared setting:
git config core.sharedRepository # "", "group", etc...
echo $? # rc 0 means shared, rc 1 means NOT shared
Solution:
cd /path/to/repo.git chgrp -R groupname . chmod -R g+rwX . find . -type d -exec chmod g+s '{}' +
# set share setting git config core.sharedRepository group # set group shared
# Verify: git config core.sharedRepository # "group"
If you really hate permissions:
git config core.sharedRepository world
Not sure what level this does:
git config core.sharedRepository true
References:
- Git Push Error: insufficient permission for adding an object to repository database - Stack Overflow - http://stackoverflow.com/questions/6448242/git-push-error-insufficient-permission-for-adding-an-object-to-repository-datab
Windows SSH Debugging
set GIT_SSH_COMMAND=ssh -vvv
ref: [34]
Windows No Mutual Signature Algorithm
Set verbose:
set GIT_SSH_COMMAND=ssh -vvv
Try the git command:
git clone...
Error:
debug1: send_pubkey_test: no mutual signature algorithm
In order to re-enable ssh-rsa support, inserting the following line into the affected SSH client's config file can re-enable this algorithm:
PubkeyAcceptedKeyTypes +ssh-rsa
ref: [35]
Notes
To Read
SVN for Git:
- http://git-scm.com/course/svn.html
- https://github.com/blog/626-announcing-svn-support
- http://hub.witness.org/en/blog/yat-tibet
- http://help.github.com/svn-importing/
- https://github.com/blog/644-subversion-write-support
- https://github.com/blog/626-announcing-svn-support
- http://learn.github.com/p/git-svn.html
- http://stackoverflow.com/questions/807782/google-code-svn-or-github-git
- http://tomas.markauskas.net/en/blog/20100505-github-subversion-support
- https://github.com/blog/626-announcing-svn-support
- https://github.com/blog/644-subversion-write-support
- https://github.com/blog/31-back-to-subversion
- http://svnhub.com/
- https://github.com/blog/31-back-to-subversion
- http://git-scm.com/course/svn.html
- https://github.com/blog/626-announcing-svn-support
- https://github.com/blog/626-announcing-svn-support
- http://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-rename.html
- http://www.devdaily.com/blog/post/svn/move-directory-with-subversion-svn
- http://book.git-scm.com/4_undoing_in_git_-_reset,_checkout_and_revert.html
keywords
- ↑ https://stackoverflow.com/questions/5308816/how-can-i-merge-multiple-commits-onto-another-branch-as-a-single-squashed-commit
- ↑ https://stackoverflow.com/questions/1670970/how-to-cherry-pick-multiple-commits
- ↑ https://stackoverflow.com/questions/5120038/is-it-possible-to-cherry-pick-a-commit-from-another-git-repository
- ↑ https://stackoverflow.com/questions/50800829/compile-git-without-gettext?newreg=5ed483890d174baf8ac5b4ee1edf0acb
- ↑ https://stackoverflow.com/questions/13965391/how-do-i-see-the-commit-differences-between-branches-in-git