Source Control

Jump to:

                                centralized scm                 distributed scm
                                =============================   ====================================
task:  			     	svn		rcs		git 			hg/mercurial	
-----------------------------   --------------- -------------   ----------------------- -------------
update repo:			up		co?
check out			co 		co		clone			clone
                                                                checkout tags/2.2
lock file for edit		not needed?	co -l		not needed
check in			ci		ci		commit -a, push	

what has changed?		status				status
diff b/w current and repo:	diff		rcsdiff		diff			diff
change list:			log		rcs log		log --oneline

git (and mercurial hg) is a distributed source control system. Traditional scm like svn, cvs, p4, rcs, are centralized system and has a single primary repo. git has a very different mode operandi than the traditional system, thus the table of "equivalent" commands above is somewhat misleading. RTFM!! =)

SVN Subversion commands

svn checkout http://svn-server/path/to/project	localDirName
	# download all files related to a svn project/repo
	# storing all files in a subfolder called "localDirName"
	# .svn/entries should have the URL of the source

svn info	# tell where svn tree source info
svn add  file	# add a file into svn repo  (this auto check in the file??)
svn mkdir foo	# create a new dir and have it added to repo (after ci)

svn ci 			# check in, ie, commit changes into svn
svn ci file1 file2	# check in only specified file(s).  note that removing entry in the comment window does NOT remove the file from being commited!!		

svn diff file		# diff b/w working copy and last version in repo
svn diff file		# diff b/w working copy and last version in repo

proxy settings.  Unfortunately don't seems to have a cli method to change it.  
playing with exceptions maybe the trick.
it does NOT heed environment variable http_proxy
edit $HOME/.subversion/server 
in the global section, there are several proxy clauses, eg
###   http-proxy-host            Proxy host for HTTP connection$
###   http-proxy-port            Port number of proxy host service$
###   http-proxy-username        Username for auth to proxy service$
###   http-proxy-password        Password for auth to proxy service$
###   http-proxy-exceptions      List of sites that do not use proxy$

If cached password has been changed, 
rm ~/.subversion/auth
(caching password is not recommended, svn does warn that it is not secure... 
but didn't see cleartext password stored there, 
maybe is is simple obfuscation rather than real encryption.  
and file could be copied... )

svnadmin create		# these are admin commands, such as create a new svn repository.

Granting user read (r) or read/write (rw) access to a svn repo, edit 
be careful with typo.  a single mistake will render the file unparseable and no one would be able to use svn !!

svnlook info somerepo		# these will look at a repo w/o checking it out
svnlook log  somerepo
svnlook tree somerepo

Tortoise SVN is a simple, lightweight SVN client avail in windows.


$CVSROOT                the source dir
$PROJROOT               the local dir where copy of cvs is placed, this is the
edit place till changes are commited

so far, only successful by checking out files while pwd=$PROJROOT, and then spe
cify full path for file.  if just specify dir name, the whole sub dir is checke
d out

cvs co dir/filename     check out file
cvs add                 add file to c vs tree
cvs commit              make changes permanenet


RCS is pretty old school. It does work out of a simple directory on the file system, no external server needed.
co -l {filename} check out file (with lock) from rcs sys
co -r {filename} check out revision  or the latest verstion,
                 will prompt to overwrite co -l files (at least then when you do ci, it will say file not changed
                 and effectively reversed to original content)
ci    {filename} put file back into rcs
ci -u {filename} (the -u leave a read only copy of the file, as if run co immediately after ci, always use it:))

rlog {file}     display rcs edit log
rcsdiff {file}  display diff b/w current file content and its previous version
rcsdiff -r1.1   display diff b/w current file and version 1.1 of the file
rcs -u {file}   forces an unlock a file locked by some other user.
rcs -aUID FILE  add access for user UID to the FILE (but didn't work, maybe file need to be group writable).


if submit has problems, can do:

p4 revert -a    = revert files that have not been edited (no changes)
                                  very useful after accidental p4 edit ... !!!
p4 revert               = note, old changes to file will be DELETED.
p4 change -d {change#}  = remove change request

p4 changes -m100        = check for list of changes, use grep to find my own.  (-m100 show last 100 changes only.  the cmd shows all historical data).

to sync files in selected dir only.
cd to the desired dir, then do:
p4 sync ...

or, pf sync /path/to/dir/...
the '...' indicate the 'files in this position at the depot'.

sync against a known date/time

p4 sync ...@"2002/06/22 00:01"
Time can be omitted, it will default to the beginning of that date (not the end!)

sync against a label?

p4 diff FILE
the entries marked by '<' is my own file
and those in '>' is the file in p4

(diff file1 file2, < is left file1, > is right file2, so I guess p4 diff check
out a file as temp and use that as file2).

p4 diff FILE#1 FILE#3
compare version 1 and 3 of FILE

p4 sync -n ...          # just see changes for current dir
p4 sync -f ...          # force all update on current dir (only force refresh of
files not checked out, as in refresh accidental removal of non locked file.
those that have been updated remains open, no accidental erasure cuz of
refresh )

p4 opened ...           # list of files opened
p4 edit {file}          # open a file for editing

p4 branches                     # list p4 branches that can be added to client view.

p4 log... ?             # see revision history of file

zmbl stuff?
p4rename        : script to rename a file checked into P4.

   FILETYPE one of symlink, etc

change file to executable
p4 edit -t kxtext FILE
p4 submit


git is a very different beast than the other traditional source control system. Instead of having a "code centric" view to create trees and branches, git is more of a "developer centric" paradigm. As such, many actions don't have the same parallel as say SVN, even though some commands seems similar on the surface.

git works as a two stage commit. commands to manipulate the local git database which is the central view of the scm. Additionally, git can sync to a remote server (think github), and this is the repo server where many collaborators "check in" their codes for sharing.

diagram for git workflow

Downloading open source sw
git clone	# download the whole sw repo
git tag								# see available tagged releases
git checkout tags/2.2						# switch to use the named tag release (2.2)

git against local copy of repository
diagram for git workflow within developer's laptop

git clone			# create a local copy of a source code tree
git commit -a 			# most basic workflow after edit, most like svn, commit all changes

git commit file1 file2		# check into local copy (but other don't see this change yet)
git commit file1 -m "comment"	# provide check in comment on cli rather than launch editor

git add file			# kinda feel like "add new file to be tracked"
				# but really is adding changes into the git db
git add -p 			# patch-based add (allow committing chunk of code at a time rather than whole file)

git status			# show commit staatus within the local copy of repo only.  
				# if the clone had been some time and master had seen other commits, 
				# it will NOT show up in the status command.  
				# only another git fetch would get these changes.

## think these are still acting on local copy.  in fact, it is likely that 
## git act on local copy, except for few commands to interact with master repo...

git log file1
git log 
git log --oneline         	# compact log, easier to read!
git log --oneline file		# changes pertaining to the specified file only
git log --oneline issue123	# changes pertaining to the specified branch only  (?)
git log --decorate
git log --graph			# 
git log --oneline --graph --decorate	# can alias to "lol" for this oft use combo
git log -p 			# patch: show diff introduced by each change (instead of just commit msg for the log)

git log -p [-1] PATH/FILE	# list last -N COMMITED changes.  Current edit against git repo is NOT shown!
git diff ??			# find how PATH/FILE differ from current state with last commit in git
gitk FILE			# GUI tool to see commits/diff (but not branches?)

git log issue123 ^master	# branch diff, changes in branch issue123 but NOT in master
				# ^ indicate "not in"

git show COMMIT_HASH		# details of the commit

git branch			# list branches.  * indicate the current branch working on.
git branch -r			# list all branches avail in (r)emote server
git branch issue123		# create a branch called "issue123" (eg after a bug#)
git branch --edit-description issue123	# modify a description for the named branch.  it brings up a text editor
git branch --list -v    	# list branches and descriptioins
				# actually, the info is last commit msg, branch desc so far only visible in the editor that comes up when using --edit-descriptiong.  thus, also  using git_branch.rst file... but 
git checkout -b issue123	# create a branch and switch to it at the same time (?)
git push -u origin issue123	# push the local branch "issue123" to origin (github) [can push branch tag up upstream even when there are 0 commits]

git tag -a  v0.5   2128f04 -m "eg of adding a tag at a specific commit point"
git push --tags  origin master

git tag -a         2018_0901_wsl -m "wsl git hopefully not creating cr/lf chaos"  	# create a release 
git push -u origin 2018_0901_wsl							# push the tag to github

# resync a branch from master (ie master is ahead, have changes that should be incorporated into the branch)
git checkout master		# swich to the master branch (master is trunk branch created by default)
git pull
git checkout issue123		# so sitting on the branch issue123
git merge master		# resync changes done to master into issue123 branch (if master is ahead of issue123)

# merge changes done in a branch into master (ie issue123 is ahead of master and ready to "upload/publish")
# could use web gui in github, which is considered a Pull Request.
# or:
git checkout master		# so sitting on master branch
git merge issue123		# retrieve changes in issue123 branchand merge into current (since sitting on master)

git checkout filename.txt #  retrieve filename.txt from repo, discarding local changes (for uncommited changes?)

git mergetool			# launch visual diff tool

git init 			# create a git repo based on content of the current dir (and sub dirs)

git remote add     repoName url	# set a repo name for current "git dir", and url in github where it would upload to
git remote set-url repoName url	# use this if need to change remote github/bitbucket url
				# url for the named repo need to be pre-created in github, bitbucket, etc

git push --set-upstream repoName master	# the first push to a new repo need to specify the repository and branch name 

git reset			# abandone current uncommited changes.  ie revert files to state in the git repo
git clean -nd			# clean is to remove all untracked files in the current dir.   -nd = preview/dry run
git clean -id			# -i for interactive.  -f for force.

git revert			# abandone changes in a checkout ?
git reset head			# undo "git add"

git log --diff-filter=D --summary | grep delete		# list all deleted files in github
git checkout SHA^ -- ./filename				# restore a file.  ^ means right before the commit

git ls-files -d | xargs git checkout -- 					# undelete all unstaged deletion (those not commited yet)
git status | grep 'deleted:' | awk '{print $2}' | xargs git checkout --		# recover  all staged delete (after commit)	

git against "origin"
origin is typically the developer's central repo hosted on github,
or the hosting location of a fork of a project.

git push			# get local copy pushed into "central", or source of clone.  other will get the changes now.
				# this uses the default, which really means git push origin master # for primary source, master branch.

git push origin master		# what "git push" is doing when other params are omitted
				# pushes my current "master" branch to central repo "origin" by uploading data (to github)

git pull			# sync local git db with the remote server db (eg github, aka central)
				# recommend to do this before pushing changes back to central.
				# pull (from central) daily or so when working on a branch to keep code merges manageable
				# and the pull does not "post" my local changes to central so no one knows about the local work 

git pull --rebase		# may want to do this before commit... so conflicts are local.
				# rebase has to do with where to insert changes into the original tree... 
				# rebase is typically the most desirable option
				# BUT...
				# in corp env, almost always better to use fetch and merge than pull --rebase
				# Hmm...

git fetch 			# get changes on master repo and sync them to local copy of the repo.  
				# conflict may arise from this.  
				# better resolve conflict here before committing/pushing.

git merge 			# merge branch

# it is prefered to resolve conflicts in local copy, 
# rather than push the changes out
# and have everyone look at changes at the global level, 
# which may cause lot of conflict in other's code.

# config git to use proxy
# note that shell env var http_proxy isn't heeded
git config --global http.proxy

git config --global --unset http.proxy

git config --global alias.proxy   "config --global http.proxy"
git config --global alias.noproxy "config --global --unset http.proxy"

git config --global "log --oneline --graph --decorate"		# create alias "git lol"   # logd

git against "upstream"
upstream usually refer to the "grand daddy" repo of an open source project, where Pull Requests are submitted to add one's contribution to the open source project.
Example workflow can be seen at Singularity documentationcontribution page.

# fork the project 
# git clone the fork above

git checkout master
git remote add "upstream"

# made changes
git commit ...

# goal is to make any conflicting changes locally and 
# address them before pushing it upstream 
# where many other folks will see conflict and be affected by it

git pull upstream master		# resync upstream (grand daddy repo) to my master (what i forked)
git pull --rebase upstream master	# (same as?) `git pull --rebase`
# perform any necessary merges
git commit ...
git push origin master 			# (same as?) `git push`

# create Pull Request on 
# forks are tracked by, the PR will submit the changes to the grand daddy repo.

dealing with conflicts
git config merge.conflictstyle diff3 will got a long way in automatically merging differences. And those that actually have conflicting lines will be marked clearly in the file, search for <<<< |||| >>>>

There are also visual diff tools. command line method using branch can also be used. Refer to post in stackoverflow for many other gory options.

git terminology

Example instructions to add files as git repo into github
git config ""
git config  "tin"

# can use git config --global  if no need to use diff settings per repository
git config --global credential.helper 'cache --timeout=3600'
git config --global github.user   tin6150
git config --global github.token  mytoken
git config --global color.ui      true

git remote add origin
git push -u origin master

git in windows
Install wsl
sudo apt install git
This is pretty usable.
can have the git run outside the lxfs subsystem, eg cd /mnt/c/... and git clone into a folder there. it works too.
Use terminal like Cmnder or apt get install lxterminal and use with like XcSvr.
These notes are pre WSL, or if it was ever desired to use git but not WSL...

There is a git client for windows, but the cli didn't suite my taste and need :(
in the git-bash terminal, git push will prompt for username in the cli, and a pop up GUI window for password.

Cygwin and MobaXterm has provided a quite usable unix-like bash environment for windoze. However, getting git to work has been very tricky :( The following info from stack overflow may help...
export HOME=/c # in MINGW64 from PortableGit bash terminal

At the end, cygwin with the git that it ships with worked out okay for me, but it is not usable inside a mobaXterm tab.
export HOMEPATH=\

git TUI client
git GUI client
git references

mercurial hg commands

hg clone
hg update stable
	# setup and download the galaxy repo from bitbucket

Git the Princess

Thanks to the folks at toggl


(cc) Tin Ho. See main page for copyright info.