Git
- General
- A visual reference to GIT
- Git Book: Read chapters 2 and 3
- Specific
In the next lines, we will try to explain equivalences from svn typical commands to git ones.
svn command | git equivalence |
---|---|
svn checkout _repositoryURI_ | git clone _repositoryURI_ |
svn add _file1__ | git add _file1_ |
svn commit -m ... | git commit -m ... ; git push |
svn update | git pull |
Enable Git in sourceforge
- Login as a project administrator and go to the Develop page for your project.
- From the Project Admin menu, select Feature Settings
- Select the Available Features tab
- Check the box for Git; your repository will be instantly enabled, and the heading for Git should move from the Available Features tab to the Enabled Features tab.
Copy from svn to git
git svn clone [https://newxmippdoc.svn.sourceforge.net/svnroot/newxmippdoc](https://newxmippdoc.svn.sourceforge.net/svnroot/newxmippdoc) newxmippdoc-git cd newxmippdoc-git/ git config user.name "USERNAME" git remote add origin ssh://USERNAME@newxmippdoc.git.sourceforge.net/gitroot/newxmippdoc/newxmippdoc git config branch.master.remote origin git config branch.master.merge refs/heads/master git push origin master
If git clone has interrumped then cd to the repository and continue with the commandgit svn fetch
https://sourceforge.net/account/services
Download using
git clone git://git.code.sf.net/p/newxmipp/code newxmipp-code (read/write)
If you do not want to type your password each type you use git copy your public ssh certificate to sourceforge using the interface
https://sourceforge.net/account/ssh
http://www.vogella.de/articles/Git/article#firstgit
(Git does not work with single files but with the whole repository, no single files checkouts)
Git is not a centralized system. It has been designed to interact with any other git repository (for the same project). A git server may be installed but ssh is adequate for sporadic interchanges ssh may be used
- Clone git repository at clark.cnb.uam.es in pepe.cnb.uam.es.
In pepe type
git clone ssh://username@clark.cnb.uam.es/home/username/xmipp
- Update pepe (changes made and committed in clark). In pepe type
git pull
(pepe knows that should access clark because the repository was cloned from there, it is also posible to update other repositories) * Update clark (changes made in pepe) In pepe
git push
(remember to commit first) In clark
git checkout
To push to a different directory from which you clone the code:git push path/to/other/repo
Git centralized repository You may use the above approach to create a git centralized repository Init bare git repository in main server (I will call this repository aGEM)
SERVER mkdir aGEM cd aGEM git --bare init
In client we have directory aGEM-dev with code
CLIENT1 #go to directory with code and create repository #create git repository mkdir aGEM-dev cd aGEM-dev ####cp -r ../aGEM/* . git init git add . git commit -m "create git repository"
send code to main repository
#push to server #add auxiliary label remote git remote add origin ssh://nataly@biocomp.cnb.csic.es/natalia/aGEM git push origin master
Delete local repository an retrieve it from main server
#delete client 1 git server and do as in client2ssh://nataly@biocomp.cnb.csic.es/home/natalia/aGEM aGEM-dev
Create new file and push it to main server
#CLIENT1 add new file (locally)vi c.c git add c.c git commit -m "comment c" c.c
#push to main server git push
create branch for realese 2.0
##branches git branch -a git checkout -b release2.0 git push origin release2.0### Revert merge if this has not been committed to Sourceforge###git checkout release2.0
#retrieve old version
Move the pointer of our branch to a previous commit:
git reset --soft HEAD^
The unwanted commit will be removed automatically by git.
- create a branch called master2 from the commit previous the merge commit.
git branch master2 HASH
- Delete master branch:
git checkout 3.0 git branch -D master
- Rename master2 to master:
git branch -m master2 master
- In Sourceforge remove master branch:
git symbolic-ref HEAD refs/heads/3.0 git branch -D master
- Pull the new master branch (from local repository):
git checkout master git pull origin master
- In Sourceforge set HEAD to master again:
git symbolic-ref HEAD refs/heads/master
ssh -t user,project@shell.sourceforge.net create
git config --add branch.3.0.remote origin git config --add branch.3.0.merge refs/heads/3.0
If you want to revert changes made to your working copy, do this:
git checkout .
If you want to revert changes made to the index (i.e., that you have added), do this:
git reset
If you want to revert a change that you have committed, do this:
git revert ...
Often, when you’ve been working on part of your project, things are in a messy state and you want to switch branches for a bit to work on something else. The problem is, you don’t want to do a commit of half-done work just so you can get back to this point later. The answer to this issue is the git stash command.
$ git stash
At this point, you can easily switch branches and do work elsewhere; your changes are stored on your stack. To see which stashes you’ve stored, you can use
git stash list:
You can reapply the one you just stashed by using the command shown in the help output of the original stash command:
git stash apply
more: http://git-scm.com/book/en/Git-Tools-Stashing
git branch newBranch git commit -m "Your comments" yourFiles git push -u origin newBranch
git branch -a
In a different branch from the one you want to remove, do
git branch -d oldBranch
The previous command does not allow to locally remove unless the oldBranch has been merged to another branch. If you want, anyway to locally remove the branch do
git branch -D oldBranch
In a different branch from the one you want to remove, do
git push origin :remoteBranch
Everybody else has to "update" the list of branches in the origin, so that they also get it deleted. To do so
git remote prune origin
git checkout branchToClose git commit -m "Your comments" allFilesToCommit git push git checkout anotherBranch git merge branchToClose git branch -d branchToClose git push origin :branchToClose
To create a local branch at the status of a remote branch:
git checkout -b newlocalbranchname origin/remotebranchname
To create a branch and also set to track the remote branch:
git checkout -t origin/branch-name [-b newlocalbranch]
If you want to repeat one change you did (in one commit) in one branch within another branch, use cherry-picking. To do so, first do the commit as usually and remember (copy) the commit id. Then checkout to the destination branch, update it with the last modifications, and execute
git cherry-pick COMMIT_ID
This creates the commit in the second branch, so you don't need to execute a git commit command. But if you want the change to be uploaded to the remote server, you may want to execute a git push.
If the changes you want to repeat in the other branch are not localizated in just one commit, but in more than one, you can copy all the commits from one branch to another using the rebase utility. For that purpose, it's needed to know the commits hierarchy. Imagine a commit distribution like this...
ab546 --> b45a3 --> ca5ba --> 3651c (master) | +-> 657ca --> 245ac --> 89a1b (testing)
There you have 2 branches (master and testing) and you need to add the changes introduced in testing from 245ac commit into master branch. To do so you need to checkout to testing branch and execute...
git rebase --onto master 657ca
Note that the commit written in the rebase command is excluded from the rebase. With that command, you will get the following scenario...
ab546 --> b45a3 --> ca5ba --> 3651c (master) --> 478ca [copy of 245ac] --> 18b34 [copy of 89a1b] (testing) | +-> 657ca --> 245ac --> 89a1b
In the case of the rebase, you have to be careful, because testing pointer is also moved with the commits, so if you don't checkout again to 89a1b commit and create a new pointer that references it, the garbage collector will act and delete the non-referenced commits (in this case, all the old-named testing branch)
In case of looking for a commit by date, the repository can be moved by:
git co git rev-list -n 1 --before="2011-06-21 13:37" master
git log origin/master..master
git diff origin/branch --name-only
git diff branch1 branch2 --name-only
Let's say you are in the middle of a merging, and you regret from the changes you have already been introducing. Files that are not related to the merging conflicts are unaffected by this command.
git merge --abort
Let's say we're happy with the code at a certain state, or at least, that we have to release the code at that state. For that purpose we need to set a tag. We go to the desired commit and then...
git tag -a 3.1-release -m '3.1 Xmipp oficial version'
being 3.1-release the name of the tag and the text after -m will be the description that will define the tag
After that, you'll need to upload it to the repository, by writing...
git push --tags
If you want to, for example, move the 3.1-release tag to one commit to another and you already commited and pushed it, it's not enough deleting it in your working copy and establishing it again. You first need to delete from remote repository by typing...
git tag -d 3.1-release
(delete local tag)
git push origin :refs/tags/3.1-release
After that, the deletion has been completed in the remote repository and then you can proceed adding a new tag with the same name and pushing it as usually
#################################
# SCRIPT TO AMMEND USER COMMITS #
#################################
INCORRECT_MAIL=
CORRECT_NAME=
if test $# -eq 2; then
INCORRECT_MAIL=$1
CORRECT_NAME=$2
CORRECT_MAIL=$1
elif test $# -eq 3; then
INCORRECT_MAIL=$1
CORRECT_NAME=$2
CORRECT_MAIL=$3
else
echo "ERROR: this script only takes 2/3 arguments:"
echo "argument 1: mail of the committer to change"
echo "argument 2: name that will be written to that committer"
echo "(optional) argument 3: mail that will replace the former one"
exit 1
fi
echo "INCORRECT MAIL: $INCORRECT_MAIL"
echo "CORRECT NAME: $CORRECT_NAME"
echo "CORRECT MAIL: $CORRECT_MAIL"
git filter-branch --env-filter 'if [ "$GIT_AUTHOR_EMAIL" = '"$INCORRECT_MAIL"' ]; then
GIT_AUTHOR_EMAIL='"$CORRECT_MAIL"';
GIT_AUTHOR_NAME='"$CORRECT_NAME"'; fi' -- --all
Imagine you pushed to the repository using different machines. It is recommended for you to do...
git config --global user.name "Your Name"
git config --global user.email "your@email.domain"
...but let''s say you forget the name you used last time. Your name is Pepe Rodriguez and you used Pepe Rodri in one machine but Pepe R in another different machine. By the time you realize that, a lot of time has passed and you pushed thousands of commits from each machine. How to unify that into one single name for every commit? Here's where the script from above appears into scene. You can use it (it executes git filter-branch) to re-write every commit for unifying your name, and for changing your email into another. If you execute it with 2 args, you'll just re-write every commit with the given e-mail into the given name. If you put 3 args, then you will be also giving the new e-mail you want to write into those commits.
Sometimes sourceforge code webpages can stop working. In our experience, this can be because a missing post-receive hook in the repository. In that case, you need to access the sourceforge repostory via ssh, and, inside hook folder, add the following script named as "post-receive":
#!/bin/bash
# The following is required for site integration, do not remove/modify.
# Place user hook code in post-receive-user and it will be called from here.
curl -s http://sourceforge.net/auth/refresh_repo/p/PROJECTNAME/MOUNTPOINT/
DIR="$(dirname "${BASH_SOURCE[0]}")"
if [ -x $DIR/post-receive-user ]; then
exec $DIR/post-receive-user
fi
That will do the job. In the specific case of Xmipp, this is placed in /home/git/p/newxmipp/code.git/hooks/post-receive and its code is
#!/bin/bash
# The following is required for site integration, do not remove/modify.
# Place user hook code in post-receive-user and it will be called from here.
curl -s http://sourceforge.net/auth/refresh_repo/p/newxmipp/code/
DIR="$(dirname "${BASH_SOURCE[0]}")"
if [ -x $DIR/post-receive-user ]; then
exec $DIR/post-receive-user
fi