GIT - Source Control
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.
Downloading open source sw
git clone https://github.com/singularityware/singularity.git # download the whole sw repo
git tag # see available tagged releases
git tag -l -n99 # get description of tag as well, first 99 tags
git checkout tags/2.2 # switch to use the named tag release (2.2)
git against local copy of repository
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.
git status -uno # or --untracked-files=no ## dont show untracked files
git status -s | grep "^ M " # short mode, untracked files prefixed with ??
## 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 branch -d issue123 # delete local branch
git branch --delete issue123 # delete local branch FORCEFULLY ie, even if NOT merged or pushed yet
git push origin --delete issue123 # delete remote branch
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
git tag # list all tags
git tag show v0.5 # show description of the specified tag
git tag show --tags # long output with tag desc and commit diff
# https://stackoverflow.com/questions/16329776/how-to-keep-a-git-branch-in-sync-with-master
# 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 vs upstream?
origin is typically the developer's central repo hosted on github,
or the hosting location of a fork of a project.
For team, non forked project, origin is the central repo residing on github.com or bitbucket.com
If fork is involved, see upstream below.
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...
# --rebase may work well between diff branches, where conflict files are few, changes between contributor are in "islands".
# --rebase may NOT be so good w/in a branch of single contributor, since the edits on different machines likely rooted on same base and don't want to `rebase` that.
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 http://proxy01.eville.com:2011
git config --global --unset http.proxy
git config --global alias.proxy "config --global http.proxy http://proxy01.eville.com:2011"
git config --global alias.noproxy "config --global --unset http.proxy"
git config --global alias.lol "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" https://github.com/singularityware/singularityware.github.io
# 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
# below refer to push directly to master, though most project probably should commit to a dev branch of sort.
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 github.com
# forks are tracked by github.com, the PR will submit the changes to the grand daddy repo.
git between branches
- create a new branch, make changes, commit, close off branch once it is done
- Before branching, checkout into the branch where the merge will eventually be done against. eg git checkout dev; git branch tin-dev
git checkout tin
git pull origin dev # pull from origin, the dev branch, into the branch i am sitting in.
# do this before commit changes, help keep branch uptodate
git pull --rebase origin dev # --rebase seems to work out better when "parent" (dev) branch has lots of changes that I just want to keep.
# git commit and push after pull should produce desirable result
--0--
git fetch # update all branches ?
--0--
git checkout tin
# merge had been really messy/fuzzy...
git merge develop # pull changes from develop branch into the repo I am sitting in (tin)
git push origin tin # ie git push? get my local changes into "origin" (bitbucket)
overall idea is to pull/fetch all changes into the branch I am doing edit.
resolve all conflicts (merge) locally.
then push the changes/commits into origin (bitbucket), then create PR.
If already created PR,
still fetch all changes from "parent branch" locally.
resolve and commit , then PR will reflect the final change without conflic,
thereby allowing easy merge w/o conflict.
git branch --delete BRANCH_NAME # delete local branch, if all changes already pushed
git push origin --delete BRANCH_NAME # work on "origin", ie bitbucket, and remove the branch that is there. ie, it include a push right away.
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
- upstream
The main repository of a project where everone ultimate contribute their code to.
- origin
Typically one's fork of "upstream", ie, my master stored in github or bitbucket
- Fast Forward Changes
See git help push explanations.
- HEAD
A symbolic ref to current branch.
It is the parent of the commit.
github
Example instructions to add files as git repo into github
git config user.email "tin6150@gmail.com"
git config user.name "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 https://github.com/tin6150/psg.git
git push -u origin master
Client/tools
git TUI client
- tig: top-like interface, read existing git repo, no need to login.
- gs??
- fugitive, a vim bundle - https://github.com/tpope/vim-fugitive
git GUI client
- git gui : GUI version of git.
read local git repo, no need for additional login.
apt install git-gui
- gitk: GUI tool to review commits, but not branches? like a limited subset of git gui
apt install gitk
- Git Extensions: seems promising GUI. Mono app in Linux. Mac, Windoze. Need many supporting tools (git for Windows, putty) and likely github login.
- GitKraken seems highly rated, but not free for non-commercial use.
- reviews: https://www.cloudways.com/blog/best-git-gui-clients/
- sourceTree: Free, but req activation with bitbucket acc. mac and windows only, no Linux?
- https://unix.stackexchange.com/questions/48469/gui-for-git-similar-to-sourcetree
- GitEye
- SmartGit: not opensource. nice 3-way conflict resolution.
-
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.
TL;DR
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...
unset HOMEPATH
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=\
export HOMEDRIVE=H:
git references
Git the Princess
Thanks to the folks at
toggl
hoti1
bofh
bofh1