git training

41
Advanced GIT Concepts by Eric Aguayo (a.k.a. ericmaster)

Upload: eric7master

Post on 06-May-2015

1.516 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Git training

Advanced GIT Conceptsby Eric Aguayo (a.k.a. ericmaster)

Page 2: Git training

BASIC CONCEPTS

What is GIT?● DVCS

GIT Architecture● Working Copy● Staging Index (a.k.a. index)● Local Repository (a.k.a. repo or repository)● Remote Repository (a.k.a. remote)

Page 3: Git training

GIT Architecture

REMOTE SERVER

LOCAL MACHINE

WORKING COPY

DEV MACHINE

REPO

INDEX

DEV MACHINE

ORIGIN

DEV2

DEV1

DEV3

REMOTE MERGE

Page 4: Git training

GIT Architecture

Source: http://geeks.ms/blogs/etomas/archive/2011/01/18/git-para-dummies-pero-dummies-dummies-eh.aspx

Page 5: Git training

GIT ARCHITECTURE

WORKING COPY

INDEX: works as a staging area between working copy and repo

REPOGIT Objects

● blob: stores the data● tree: reference other trees and

blobs (directories)● commit: references to a tree

and contains all the info of a commit

● tag: mark a reference to a specific object

git addgit commit

Page 6: Git training

.git Directory File Structure

Contains all the information to recreate the tree history

|-- HEAD (pointer to the current branch)|-- config (holds the configuration preferences)|-- description (description of your project)|-- hooks/ (pre/post action hooks)|-- index (contains the index of the repo)|-- logs/ (a history of where the branches have been)|-- objects/ (the objects (commits, trees, blobs, tags)`-- refs/ (reference to important commit objects)

Page 7: Git training

GIT most common commands

init: Initialize a repository, initialize it empty with the --bare option or based on existing contentbranch: Creates a new branch/Show all branchesclone: Initialize a repository and working directory from a remote repositorycheckout: This has several purposes: Change branch or revert a file or directorystash: Temporarily saves the changes and wipe those changes from the index and working copy

Page 8: Git training

GIT most common commands

status: Displays informational data about the local repository, files added to the index and current branchadd: Adds changes to the staging indexcommit: Record changes into the local repositoryrebase: Used to edit commits or join commits into a single commit to cleanup tree history

Page 9: Git training

GIT most common commands

fetch: Get commits from a remote (this does not merge the commits or apply the commits to working copy)merge: Merge the commits of a branch on a remotecherry-pick: Merge a specific commit from a remotepull: Merge the changes from the origin repository on the current branchpush: Push changes to a remote repository

Page 10: Git training

GIT most common commands

rm: Deletes a file from the staging index (not deletes the physical file by itself)reset: Remove file from index or Reset (Rollback) HEAD to a specific commitrevert: Revertir un commit (not a file)diff: Shows differences between commits or branchesshow: Shows commit details (user, time and changes)log: Shows commit history

Page 11: Git training

GIT Configuration

git-config: Used to configure repository settings (/git/config file) or global settings (.gitconfig). For example:

git config --global user.name "Username"

will get the following result into .gitconfig file generally located in your home directory

[user]...name = Username...

Page 12: Git training

Git ConfigurationThese are the basic settings that every developer should set in their local environments:

git config --global user.name "Username"

git config --global user.email "[email protected]"

Also these are useful commands that will display output of some commands in a better way

git config --global color.branch autogit config --global color.diff autogit config --global color.interactive autogit config --global color.status auto

git config --global format.pretty oneline

Page 13: Git training

GIT Configuration

In a similar way we can set a specific repository configuration. For example, to set the remote origin as the default remote for the branch master

git config branch.master.remote origin

will get the following result into .git/config file

[branch "master"]...remote = origin...

Page 14: Git training

Create a new repository

We can create a new repository from any directory where we have write permissions. It is as simple as running the command

git init

In general, the origin or any repo that you want to make public must be a bare repository, in which case we will run

git init --bare

Page 15: Git training

Clone a existing repository

GIT supports different protocols to clone. Here are some examples:

git clone [email protected]:ericmaster/liquidsoap

git clone file://localhost/srv/git/liquidsoap

git clone ssh://[email protected]/srv/git/liquidsoap

The first approach we will tipically use to clone from a public repository. Second approach we will tipically use to clone from a local machine. Third approach we will tipically use to clone a repo from a server where we have an account set up.

Page 16: Git training

GIT Workflow

A tipical workflow of a git repository involves the following commands

git diff (see what is about to be commited)

git add file1 file2 file3 (adding files to the index)

git status (verify all files have been included in the staging index)

git commit -m 'some message about this commit' (record commit in the repository)

You may skip "git add" if you want to add all modified files (not new created files) by running:

git commit -a -m 'some message about this commit'

Page 17: Git training

Checking the status

This is the info that we may get when we run the "git status" command:This line will tell us in which branch we are#On branch development

This line will tell us that the current branch has 12 more commit objects than what it has in its origin.#Your branch is ahead of 'origin/development' by 12 commits.

After push to the origin git status will basically say that everything is ok by the following output:#nothing to commit (working directory clean)

This line will tell us that the branch at the origin branch has 10 more commit objects than what is in the current branch, this may indicate that we need to pull to update our working copy#Your branch is behind of 'origin/development' by 10 commits.

In many cases we will have the following output:#Your branch and 'origin/development' have diverged,

#and have 14 and 30 different commit(s) each, respectively.

This tells us that there are 14 commit objects in the current branch in your local repository that have not been pushed yet and 30 commit objects in the same branch at its origin that has not been pulled yet.

Page 18: Git training

Checking the statusThese lines will tell us which files have been added to the index# Changes to be committed:

# (use "git reset HEAD <file>..." to unstage)## modified: file1

These lines will tell us which files have been modified but not added to the index# Changes not staged for commit:

# (use "git add <file>..." to update what will be committed)

# (use "git checkout -- <file>..." to discard changes in working directory)## modified: file1

These lines will tell us that there are files that are not under tracking# Untracked files:

# (use "git add <file>..." to include in what will be committed)## filex

Page 19: Git training

Working with branchesSuppose that you have been assigned a task to create a new user profile page. You can create a separate branch for this new feature by using:

git branch feature_user_profile

To list all branches use

git branch (to list all branches in the current repository)

git branch -a (to list all branches including branches in tracked remotes)

Output of the first command should be

feature_user_profile

master*

* Indicates our current branch

Page 20: Git training

Working with branchesBesides using checkout to discard changes of a file you can use it to switch branches

git checkout feature_user_profile

Now you can make some modifications to your working copy, add those changes to the index and commit, then switch back to the master branch. You will notice that any change you make on feature_user_profile branch will not affect the master branch. Once we are done with the feature we can merge those changes back to the master branch (make sure your current branch is the master branch).

git merge feature_user_profile

git cherry-pick commit_id (in case you just need to merge a specific commit)

Page 21: Git training

Working with remotes

In a real case, you will have to work in a feature with multiple developers (each with its own working copy). At some point you will need to synchronize your code with the rest of the developers. You could push your code to the origin so others can pull but we do not want to do that because other developers' code might be affected by a work in progress, specially if you are pushing to the "master" branch or the main branch of development.

So you will need to track each developer repository as a remote. To do this you need to add the remote into your config.

ORIGIN

DEV1 DEV2 DEV3

ORIGIN

DEV1 DEV2 DEV3

AVOID

Page 22: Git training

Working with remotesFirst we add the remote with the following command (typically we will identify each remote by the owners name or a nickname easy enough to remember in this case the remote name will be "developer2")

git remote add developer2 ssh://[email protected]/home/developer2/

git config remote.developer1.fetch +refs/heads/*:refs/remotes/developer2/*

which will add the following entry in the .git/config file. First line adds the remote and assigns a url so we can know where it is. Second line allows us to track the heads of the different branches of the remote.

[remote "developer2"]

url = ssh://[email protected]/home/developer2/

fetch = +refs/heads/*:refs/remotes/developer2/*

Page 23: Git training

Working with RemotesNow we have everything we need to merge changes with a remote repository. First we need to get all the commit objects from the remote repo into our local repo with the following command:

git fetch developer2

git fetch --all (if you want to get all the commit objects from all the remotes you are tracking)

Next thing we want to do is to merge the changes into our working copy, for this we can use the merge command

git merge developer2/feature_user_profile

git pull developer2/feature_user_profile (actually git pull is a shorthand for git fetch and git merge)

If everything goes right, we should see a message telling us how many files were changed and how many line insertions/deletions were made35 files changed, 2334 insertions(+), 309 deletions(-)

Page 24: Git training

Dealing with conflictsAt some point you will have to deal with conflicts when you get a message like this after running a pull or merge command

CONFLICT (content): Merge conflict in file.txtAutomatic merge failed; fix conflicts and then commit the result.

There are many ways you can deal with conflicts, as well as there are many tools that will help you to deal with this. When a conflict occurs, your local repo will not be updated and the index will be left in a special state until you resolve the conflict and push the changes. If you run git status you will see that successfully merged files are already added to the staging index ready to be committed while conflicted files will show as

# both modified: file.txt

Both modified means that there are modifications of the file in your local branch as well as the remote branch that could not be automatically merged

Page 25: Git training

Dealing with conflictsTo resolve conflicts you need to edit the file and look for the following tags

<<<< HEAD

//Here goes the local code

====

//Here goes the incoming remote code

>>>> commit_id

There are some tools like merge-tool which can be integrated with git command line that will display in a split screen showing the local code in the left and the remote code in the right. You can also look at the conflicts with:

git diff file.txt

Clarity and good documentation of the code are determining factors in the process of resolving a commit.

Page 26: Git training

Dealing with conflictsMany times you will be able to resolve the conflicts by simple inspection of the code. For example, the HEAD of your branch might have a condition like this

if(c1 && c2){...}

while the remote commit might have something like

if(c1 && c3){...}

most likely is that this commit could be solved, depending on the case, by changing the conflicted piece to

if(c1 && c2 && c3){...} orif(c1 && c2 || c1 && c3){...}

Page 27: Git training

If the case is more complex, you can run the following command get the commit details including the author and its descriptive message and take some decision based on that:

git show commit_id

Sometimes, if we cannot solve the conflict by ourselves we can contact the developer author of the commit to get some more information that might help us to resolve the conflict. We might even decide that is better to keep "our" or "their" modifications only. In the first case we will use the following command:

git checkout --ours file.txt

otherwise we can keep their changes

git checkout --theirs file.txt

Dealing with conflicts

Page 28: Git training

Dealing with conflictsAfter you have resolved the conflict, you need to add the resolved file to the staging index and commit.

In the case you get stuck with the conflict and just decide to get back to the state before the merge you can use the following command

git reset --hard HEAD

but if you already commited the merge you can use

git reset --hard ORIG_HEAD

when we add the --hard option we are discarding any changes made to index (not the working directory) while --soft option leaves the index intact

Page 29: Git training

Checking the commit historyWhenever you find a problem or want to check for a code that was removed some time ago, you can always check the logs to see the commit history in the current branch:

git log

git log file.txt (to check the log for a specific file)

The git log command has many options to output the data you need in a better way. Check the documentation for a better explanantion of these options http://schacon.github.com/git/git-log.html.

You can also find which user edited a specific line of a file through the following command

git blame

Page 30: Git training

Creating aliasesThere are common aliases used in git repositories. For example I can add a shorthand for checkout with

git config --global alias.co checkout

Also there are other common aliases that are very useful. You can add them through the git config command or write them directly into .gitconfig file

[alias] co = checkout ci = commit st = status br = branch hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short type = cat-file -t dump = cat-file -p

Page 31: Git training

Creating Tags

The git tag command creates a static branch that we can refer later (or revert if necessary)

git tag -a v1.2 -m 'version 1.2'

To display the tags just type

git tag

Page 32: Git training

Ignoring FilesIn most of projects there are special files, typically configuration files or content files that are specific to the local working copy where they exists. We do not want to track these files through git. To prevent these to show up in the staging index just add the file names to a special file named .gitignore. This special file will typically look like this:

# Ignore any file named foo.txt.foo.txt# Ignore (generated) html files,*.html# except foo.html which is maintained by hand.!foo.html# Ignore objects and archives.*.[oa]

If you are already tracking a file through git you can remove it by running the following command and the commit

# git rm --cached foo.txt

Page 33: Git training

Rebasinggit rebase can be used to cleanup the branches tree history. Instead of merging your main development branch into your current feature work branch you rebase the development branch:

git rebase development

git rebase -i development (to interactively add commits)

which will discard your commit(s) and reapply them as patches after the HEAD of the development branch. If in any case you get a conflict, use the following command after resolving the conflict

git rebase --continue

also you may cancel the rebase process by

git rebase --abort

Page 34: Git training

Stashing changesIn any project, you may often want to pull to update your working copy but do not want to commit your code yet. Git will not let you pull if the incoming commit(s) belongs to a file that you are editing. In this case you can temporarily save your changes and "revert" to the HEAD of your repo with the following command

git stash

This is also useful if you need to perform a quick fix without needing to commit or discard the changes of your current task, or even create a new branch. Once you are done with the changes, just run the following command to get your save changes back

git stash pop

Page 35: Git training

Hooks

GIT allows you to implement hooks to execute certain events occur in your repo. For example you might need to change some setting files in your working directory before you switch to another branch. This can be implemented in a hook.

Under the .git/hooks directory you can find files that you can edit to perform processing on determined events. For example you can use the file

.git/hooks/post-commit

to notify to some system that a commit was made

Page 37: Git training

Common issuesI deleted a file how to commit that change to my local repo?

There are two options:

git add -A .

git commit -m

or

git commit -a -m.

Note: git commit -a -m does NOT add new created files to the staging index

Page 38: Git training

Common issuesI made a commit but I want to correct the message or forgot to add my username or email

To correct the message of the last commit use:

git commit --amend -m 'correct message'

To correct the message of commit previous to the HEAD commit you can use:

git rebase -i commit_id^

then change "pick" to "edit" in the interactive mode for commit_id, make the changes and then rungit commit --amend

git rebase continue

Page 39: Git training

Common issues

I need to revert a commit given by a specific commit_id

Just run the following command

git revert commit_id

this will revert the commit object and commit the revert. Add the --no-commit option to leave the changes in the staging index for any further modification before commit

Note: this might lead to conflicts if the subsequent commits have overlapped changes.

Page 40: Git training

Common issuesI need to work in team with a developer who created a new branch for a specific feature. How do I clone that branch over my current working copy?

After adding the remote "developer", just run the following command

git checkout --track -b new_feature developer/new_feature

this will create the new repo and add the necessary branch settings in the .git/config file

Page 41: Git training

GIT Workshop

ssh://[email protected]/srv/gitworkshop/not_bare_repo

ssh://[email protected]/srv/gitworkshop/repo