Showing posts with label git. Show all posts
Showing posts with label git. Show all posts

Tuesday, June 23, 2015

A quick Git tutorial part4

 

gitignore
A common problem when adding .gitignore file is some undesired files are already tracked by Git.
To solve this problem, you need to do the following:
git rm -r --cached .
git add .
git commit -m ".gitignore is now working"
 
Solution is found here: http://stackoverflow.com/a/1139797
 
 

Monday, March 11, 2013

A quick Git tutorial part 3

Link to a well explained git tutorial
gitref.org

git remote
If you clone a project from another machine, Git automatically sets the remote machine as the origin of the project. So when you want to update with the latest updates of the project you simply do:
git pull

With 'git remote' you can list your remote aliases, so this also means you can add remote machines that has the same git repo:
git remote add alias url
 
This way you can push new changes to a specific machine by giving the remote alias argument, for example:
git push yozef

Of course, you can also remove the alias:
git remote rm yozef

To show the remote list with extra information:
git remote -v

You can change url of an existing alias:
git remote set-url origin git://some.remote.machine/repo.git

To remove untracked files and folders after hard reset:
git clean -f -d

Tuesday, March 5, 2013

A quick Git tutorial part 2

git rm
With 'git rm' we remove a file from the staging index AND from disk. So be careful if you don't want to remove it from disk! If you only want to remove a file from the staging index, you should use:
git rm --cached file

This will remove a file from the staging index and leaves the file on the disk. Sometimes you accidentally added a file you don't wish Git to track it. So the most simple procedure is to perform 'git rm --cached file', than add this file name in the .gitignore file and than finally commit. But what if you have like hundreds of files added in a folder you don't want Git to track them. For this, you can get them out of the staging index like this:
git rm --cached -r folder

Don't forget to add a line in .gitignore file to tell Git to ignore all the files in that particular folder, something like: sources/somefolder/*


git reset
With 'git reset' you actually reset your changes back to the original HEAD (the last commit revision before adding changes). Sometimes you don't know what happened and you get frustrated as everything seems to go wrong. In that case, your last action to the rescue is to go back to HEAD and everything gets wiped out. There is no way in turning back, so be careful.
With 'git reset --hard', the changes in the staging index will be undone and thus completely removed. It's the same as going back to the last commit and no changes are made yet. Notice that HEAD could also be a commit revision. If you want to go back to a previous commit, you could also do:
git reset --hard HEAD^
or
git reset --hard b45ac81

The latter brings you back to the commit with the first seven characters of the sha (in that case ' b45ac81').
If you want to go to a previous commit BUT you want the changes stay in de staging index, than you can do:
git reset --soft HEAD^

With the --soft argument, the changes stays in the staging index.


git stash
Suppose we were editing some files and suddenly a bugfix need to be done. We could create a new branch from the current branch and fix the problem or we can save our work on a stack to get back later. The latter one is called stashing. By performing 'git stash' all the edits will be saved on a stack and you get a message like:
Saved working directory and index state WIP on master: 56490c0 cool stuff with git
HEAD is now at 56490c0 cool stuff with git

You can do some more edits and save this on a stack too. To see what work we have save, we can list them with the following command:
git stash list
result:
stash@{0}: WIP on master: c761ca7 experimenting with git
stash@{1}: WIP on master: 56490c0 cool stuff with git

The top of the stack is 0 and the stack is a LIFO.
WIP could mean Work In Progress, seems logic to me, but it could mean something else.
The master means the master branch, so the message is quite clear.
Anyway, now we want to get the edits back we saved earlier, as we solved a bugfix, this is how we do:
git stash apply
This will get the 'changes' back where we left off. We could also use:
git stash pop
The difference is that the latter one will remove WIP from the stack, while the first one keeps the WIP on the stack. After putting back the saved WIP, we can remove it from the stack with:
git stash drop
This will remove a WIP from the top. If you want to remove them all, you could also issue the following command:
git stash clear


git commit --amend
Oops, you wrote a wrong message for a commit and you want to change that?
git commit --amend -m "my new message"


git cherry-pick
This commands can be useful if you want to add a commit from another branch to your master branch. You can imagine that while you're working on a separate branch, you already want to commit some of the work already done and not waiting until you finished your big changes on the separate branch.
We can do this by 'picking' a commit from another branch and 'insert' it in the master branch.
So suppose we are in a branch called 'test' and we've already done some commits and we're still busy doing some edits in some files. We can merge the last commit that's already done to the master branch. So we switch to the master branch:
git checkout master
Than we pick a commit, i.e. '93e8ab7', from the 'test' branch and insert it in the master branch like this:
git cherry-pick 93e8ab7

You can do this multiple times, but chances are you'll get conflicts if the same files will be committed again. To solve this, we 'git rebase' the branch on to the master branch. It's like making a custom branch compatible with the master branch. You will see that the commit hashes are changed after a rebase. From there on, you can switch to the master branch and merge the commits from your custom branch to the master.

To rebase, you go to your custom branch and do the following:
git rebase --onto master 1234abcde^
where 1234abcde^ is the commit from where you want to rebase to the master branch.
After that, you'll notice that commit sha's from 1234abcde to the last commit, will be changed, so it fits to the master branch. Now, if we switch back the master branch and do: git merge custombranch
Than all the changes will be merged to the master branch.
Play with it, cause it's a bit confusing and you better should avoid cherry-picking if not necessary.

git format-patch, git apply
When developing with a team on a project, there is often the case that you have one central source repository (based on Git) where the latest source codes maintains. It would be a mess if all developers of the team starts pushing the new codes and bugfixes. To keep the situation organized, there should be some kind of source code maintainer who checks the new codes and bugfixes before it updates the repository. What you get is developers are forced to send patches of codes to the maintainer and the maintainer checks whether it's ok or not, this way you get a controlled process of developing on a project with a team.
Well, to create a patch in Git, it's best to create a seperate branch and do your editing there. If you made a little fix, or added a new feature and you tested well, you finally create a patch, to do this you do as follows (assuming you're on a different branch):
git format-patch master
This means, make a patch from the difference between master branch and the current branch.
We could also do this:
git format-patch HEAD^^...HEAD
This means, make a patch from two previous commits ago to the last commit.(^  means previous).
We could also use commit revisions instead of HEADs.
Often you want to give a patch a name, so others have an idea what the patch is about:
git format-patch master --stdout > fix_bug_123.patch

On the other side, if you want to apply a patch in your master branch, it's just simply this (assuming you're on the master branch):
git apply fix_bug_123.patch

Understanding difference between cherry-pick and merge
When you have a custom branch to do some edits on it, you might have made multiple commits. So when you're satisfied with the final result, you want to merge it to the master branch. So you switch to the master branch and do 'git merge custombranch'. What happens is all the commits are copied to the master branch, you can see them with 'git log --oneline'. If you want to cherry-pick a commit, you actually want to copy the changes of one commit to your master branch (or whatever branch you are). So you get a new commit based on the 'changes' of your custombranch which is a different hash!
I'll add some images to get a better understanding, as there is a saying "a picture says more than thousand words".

git diff
To show what files have changed, 'git diff' shows the content of the changes, for example:
git diff
this will show the difference between the last commit and the added changes that are NOT added in the staging index
To show the changes in the staging index, do this:
git diff --cached
If you want to show both of the changes, meaning the changes in your working directory, do this:
git diff HEAD

To show the difference between two commits:
git diff HEAD^ HEAD
Note that the HEAD's could also be the sha's of the commits.




Monday, October 10, 2011

Git tips!

When you work on a project managed by Git, you have to type a lot to see status and results. For example, to seen which branch you're working on, you have to type:
#git branch
You'll see a list of branches and the one with an asterisk is the current branch you are on at the moment.

If you want to switch to another branch you have to do like:
#git chekout nameofbranch

There are some nice stuff we can do, like showing the current branch in the prompt!
Put the following lines in your .bashrc file:
export GIT_PS1_SHOWDIRTYSTATE=1
export PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\]\w\[\033[01;33m\]$(__git_ps1)\[\033[01;34m\] \$\[\033[00m\] '


Furthermore, adding .gitconfig file in your home directory will automatically change the behavior of Git. My .gitconfig looks like following:


[user]
name = My Name
email = My.Email@gmail.com


[alias]
ci = commit
co = checkout
st = status
di = diff
br = branch


[pager]
color = true


[color]
ui = true


[core]
editor = vim


[format]
pretty = oneline

Especially those alliases are cool. If I want to checkout to a branch, I can do this:
#git co nameofbranch

Tuesday, August 31, 2010

How to run git daemon (quick 'n dirty)

First, I assume you have installed git and know how to clone a project from a repository.

Create a directory where you'll keep all your projects to be cloned and go into that directory. For example, we could call our repository trunk "MyRepoFolder".
#mkdir MyRepoFolder

Now, the first thing to do is clone a bare git repository. With bare I mean a clean repo without a working tree like modified files, staged files etc. To get this, we do as follows:
# git clone --bare ~/Development/CProject/myproject/ myproject.git

Next, we create a magic file "git-daemon-export-ok" in the project's directory.
# touch myproject.git/git-daemon-export-ok

Finally you can start the daemon, in my case it would be:
#git daemon --verbose --base-path=/home/nordin/MyRepoFolder

With the --verbose option you activate some loggings to stdout, so you can see if it works when you clone myproject from another pc.

If you want to clone "myporject.git" from another Linux pc, you should do as follows:
#git clone git://my.machine.ip.address/myproject.git

If this works, you can focus on the tweakings and other detailed stuff. But that's up to you :)

Saturday, August 28, 2010

A quick Git tutorial part 1, basics.

Git basics


Git basic commands

Git init or clone
To initialize your current project with Git, you first go to your root project folder. For example, below is your project:
MyProject
    |_ sources (directory)
    |    |_ main.c
    |    |_ foo.c
    |    |_ foo.h
    |
    |_ readme.txt (file)

Your root project folder is MyProject, in this folder you execute the following command:
# git init .


This means, initialize Git in this folder to result in a Git repository.
Next, is to add all folder and files to the newly created git repository:
# git add .


Finally, check in all the files as an official commit, which means the changes are really saved:
# git commit -m "The files are offically commited in the Git repo."


The argument -m means message, because for each commit, Git wants (or even forces) you to add a comment, so afterwards you can easily read why the changes are added to this commit.

Another way is to clone a git project from a remote machine (like projects from github), use this command:
# git clone http://url.of.the.server/project.git


Once you've done that, you get a complete project with all its history, without adding or committing. From now on, you can can create new branches, add modifications and issue new commits.


Git stages
In git you have several stages. In the beginning, if you add a file in your project, the file is considered as untracked by Git. This means, that although you perform a Git commit, the untracked file is not included to the final commit! To make the newly created file trackable by Git, you issue the command "git add filename". This brings the file into the tracked stage. If we modify this same file, it is than to be considered as modified by Git. So to include the modification in Git (meaning bring the modification in the Git index), we AGAIN issue "git add filename". Now the changes are in the 'Index' stage and is ready to commit (ready to make a new snapshot for this particular version). Finally, if we (git) added all the changes, we than issue the commit command "git commit -m 'message'". Now we've walked through all the workflow processes, these are the steps you often will perform.
So the workflow is like this:

step                            status
1 new file abc.txt    : untracked
2 git add abc.txt      : tracking
3 edit abc.txt            : modified
4 git add abc.txt      : indexed (meaning ready to be committed)
5 git commit             : commit the new changes (create new snapshot)

The place where you do changes and edits on files is called the "Working tree". When you (git) add those modifications, they're put on the index stage. When committing, those modifications in the index stage are than committed for a new snapshot.


Display the commits
If you want to see all the commits of a project, you can do as follows:
# git log

This will result in a list of all  commits, the picture below gives you a portion of the output of this command:


git-log output

We see in the above picture 4 items:
  • Commit: This is the hash value of the changes that has been added, also called a revision. The hash value is a checksum for validity of the changed data. If somehow the data got corrupted, we would get an error from Git that something wrong is going on.
    In the .git folder special objects are saved for each commit which contains the changes, of course protected by sha-1.
  • Author: The one who made the changes
  • Date: date of commit
  • message: additonal note/information about this commit
You can format this output with the available arguments, like:
# git log --pretty=oneline

A nicer one is:
 # git log --graph --pretty=oneline --abbrev-commit

Concerning the hash value, it's not so important to us, it's more important for Git. You don't need to look at it all the time, except when you want to go back to some previous revision and create a release out of it, or you want to perform a git diff, to see the difference in a certain file.

git-status
If you made some changes, you can check the current status. This way you can see what files are modified before committing.
# git status


git reset
With git reset you can revert back to its original state, meaning before you made some changes to files. It may happen you made a mess and you get panic. Be relax and do the following command:
#git reset --hard

This will remove all the changes (not the changes from previous commits) and go back to its latest commit (which is also called HEAD).
(More explanation needed here...)


git tag
git tag command is very useful too if you want to give a revision a tag name for a release. We can give a tag like this:
# git tag v1.0.2 -m "bug fix"

To tag a certain commit, you can do this:
# git tag v1.0.1 -m "update" 56ae0a9

This way you give a tag name for a commit, the first 7 character of the hash are enough.
Another very cool command is to get the sources from a certain tag. It's also much easier to remember if you want to go back to the last release of your software:
# git checkout v1.0.1


git branch
A very cool feature of git is you can make a copy of your complete source for editing, while you're still in the same repository. This is called branching. Without making a copy of all your sources in your repository to another directory, you can do the some editing in another copy which is called a branch. Normally you're already in a branch, called master, which is by default. By branching, you can make a complete copy of your project but under a different name. To make a new branch, you have to specify a name, for example:
# git branch -b mynewbranch

Now you're on a copy of your complete project and do some edits. To switch back to your original branch, you do:
# git checkout master

To get a list of branches:
# git branch

The one that is marked with an asterisk (*) is the current branch you're on.
Now we go back to the newly created branch:
# git checkout mynewbranch

If we added some changes and did some commits, we would like to add the changes to our master branch. To do that, we first go back to our master branch:
# git checkout master

And than merge the changes from mynewbranch to master:
# git merge mynewbranch

To delete 'mynewbranch' as we don't use it anymore:
# git branch -d mynewbranch

NSNotification example