-
Notifications
You must be signed in to change notification settings - Fork 0
Git Basics
- Distributed source version control
- Made by Linus Torvalds.
- What the linux project uses!
- Local: Specific to the repo.
- Global: For all repositories of the user. Most common
- System: For build computers, for example. Uses the whole system.
This commands gets the user or sets the user
$ git config --global user.name
cmurphy
$ git config --global user.email
[email protected]
The gitconfig
file can be edited:
$ cat ~/.gitconfig
[user]
name = cmurphy
email = [email protected]
[gc]
autoDetach = false
- Windows uses Carriage Return Line Feed (CRLF)
- Linux/Mac uses only Line Feed (LF)
The recommended setting is:
- Windows should put the CR when pulling:
$ git config --global core.autocrlf true
- Linux uses this so files removes CR and leaves LF:
$ git config --global core.autocrlf input
Aliases allow to create own git commands with different options to make them easier to use. They can be checked by cat ~/.gitconfig
.
Some useful aliases are:
- Run status in silent mode:
$ git config --global alias.s "status -s"
- Log on special options
$ git config --global alias.lg "log --oneline --all --graph --decorate"
Git status gives the status of the git repo, and shows an error if there is no repo on the present directory.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
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: cmurphy/Git/Git_and_Github_Lessons/02_GettingStarted_with_git.md
no changes added to commit (use "git add" and/or "git commit -a")
Git init allows to make a new repository
$ git init web1
Initialized empty Git repository in C:/cmurphy/Documents/cmurphy/web1/.git
$ cd web1/
$ git status
On branch master
Initial commit
nothing to commit (create/copy files and use "git add" to track)
Git uses a 3 stage approach:
- Non staged files
- Staging area. We can change files
- Repository.
The Getting Started - Git Basics illustrates this as follows:
Git has three main states that your files can reside in: committed, modified, and staged. Committed means that the data is safely stored in your local database. Modified means that you have changed the file but have not committed it to your database yet. Staged means that you have marked a modified file in its current version to go into your next commit snapshot.
This leads us to the three main sections of a Git project: the Git directory, the working directory, and the staging area.
Working directory, staging area, and Git directory.
Figure 1-6. Working directory, staging area, and Git directory.
The Git directory is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer.
The working directory is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.
The staging area is a file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes referred to as the “index”, but it’s also common to refer to it as the staging area.
The basic Git workflow goes something like this:
You modify files in your working directory.
You stage the files, adding snapshots of them to your staging area.
You do a commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory.
If a particular version of a file is in the Git directory, it’s considered committed. If it has been modified and was added to the staging area, it is staged. And if it was changed since it was checked out but has not been staged, it is modified. In Git Basics, you’ll learn more about these states and how you can either take advantage of them or skip the staged part entirely.
$ touch index.html
$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)
$ git add .
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html
$ touch index.css
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.css
$ git add .
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.css
new file: index.html
$ git commit -m "Added home page"
[master (root-commit) 57f2084] Added home page
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 index.css
create mode 100644 index.html
- The hash allows to know the unique identifier for a commit
- Shows insertions and deletions
- Shows a code for the files, symbolic links, one for executables and one for everything else.
- Do meaningful commit messages
- Using
git status -s
on untracked files:$ git s // also git status -s ?? about.css ?? about.html ?? contact.css ?? contact.html
- To make commits in groups, not using
git add .
or individual files:$ git add ab* $ git status -s A about.css // A stands for 'Added' A about.html ?? contact.css ?? contact.html $ git commit -m "Added about us page"
- Git log allows us to look at history
-
git log
gives a complete log with complete sha1 hash, author, name, email, full commit message, date and time of commit. - For more concise:
$ git log --oneline --decorate 78ec186 (HEAD, master) Added contact us page 84f53ea Added about us page
- The HEAD is where we currently committed. Is the particular point in the git history where we are checked out. Is the stuff we have in the current working directory. You can think of
HEAD
is a reference to the top of the current branch (tree).
git clone [email protected]:ibm-cork-coderdojo-projects/git_beginners.git
cd git_beginners
echo " # cmurphy : member" >> README.md
git add README.md
git status
git commit -m "first commit"
git push -u origin master
echo "# web1" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/ibm-cork-coderdojo-projects/git_beginners_2.git
git push -u origin master
git remote add origin https://github.com/ibm-cork-coderdojo-projects/git_beginners_2.git
git push -u origin master
- Git repos can be initialized after the files already exist.
There are two ways:
- Using
git mv filename.old filename.new
. This moves the file to the staging area, but does not commit it. - Using another mean. This will make git consider the old file deleted and added a new one. To maintain the history (add all files even deleted files):
$ git add -A
Keep in mind that git add .
in git versions before 2.0 does not add the deleted files to the staging area.
Git is able to determine is the same file by using a similarity index a decimal between 0-1
where 0
is no similarity and 1
is the same. Values of similarityIndex >= 0.5
is determined by git that is the same file. For this reason, in general you should not rename files on the same commit that changes are made. This could be different for other tools. Also, don't remove a file from one place and the same commit add another similar file for the same reason.
Also two options:
- Using
git rm fileToDelete
. This removes the file and stages the deletion. - Using another mean, e.g. the file explorer, etc. This will mark the file deleted but not staged. Use
$ git add -A
to stage the changes.
Ignoring is useful to mark files so they are not in the repository. To do that, we use the .gitignore
file.
Making the ignore file will already put it into effect, if any files is affected, i.e. if there is a test.log
file in the path that has not been staged and the contents of the .gitignore
file are:
*.log
then the test.log
will be ignored. Note that the .gitignore
file is designed to be shared. If in doubt, put it on the ignore
A different git ignore file in a different directory of the file. But avoid this, since having a single file allows for a centralized place for ignoring files.
Is a blanket case, but has risks, since it ignores files in all projects you work with. To create:
$ git config --global core.excludesfile ~/.gitignore
Note: Use only for file you know no body in your team will use.
To locally ignore files, use the .git/info/exclude
file.
The precedence is as follows:
- The global
.gitignore
- The project root
.gitignore
- The local subdirectory
.gitignore
Precedence matters, so closer to the 1
on the scale, the higher priority. Also, the precedence always matter in the file. The file is read from top to bottom.
- The command
git commit -am
does "add" as well as "commit". Has a warning message, so it only works into modified tracked files. Does not work on untracked files.
-
The purpose of a branch is to allow to create an independent line of work
-
Is a local operation
-
$ git branch
shows the existing branch -
The
master
branch is the default branch. Don't usetrunk
, thats not git-like. Themaster
is the production branch -
Feature branches should be done every time a new feature is introduced. For example for creating a search feature:
$ git branch search $ git checkout search
-
When reading
git log --oneline --all --graph --decorate
, start from top to bottom. -
To push a branch to the remote we need to create it and then create a corresponding branch on the remote:
$ git checkout -b a_branch $ git push -u origin a_branch
- The
-u
option is just short for--set-setupstream
. This will add an upstream tracking reference for the current branch.
- The
- To bring a branch in a branch, go back to the branch you want to merge into and then merge the branch.
$ git checkout master $ git merge search
- To delete a branch after the merge. This does not delete the commits from the branch.
$ git branch -d search
There are two types of merges in git most commonly: fast forward and recursive.
- The fast forward merge:
- To make a branch and checkout directly:
git checkout -b categories
- Then checkout the branch to whcih to merge into and then merge the branches into it
$ git checkout master $ git merge products Updating 6c863ad..43b37e8 Fast-forward products.hmtl | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 products.hmtl
- To make a branch and checkout directly:
- No difference in history makes a fast forward merge, i.e. no difference between the master and the current branch. It is assumed the master just advances to the status of the branch.
- When both branches have different commits, the resolve needs to be done by a recursive merge, putting two streams and creating a new commit to bring them together.
-
This usually opens an editor and expects a commit message. Some OS defaults the commit message.
$ git merge categories Merge made by the 'recursive' strategy. categories.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 categories.html $ git lg * 1f2a155 (HEAD -> master) Merge branch 'categories' |\ | * d5853d8 (categories) Added categories * | 43b37e8 Commited products page |/ * 6c863ad Added search page
-
- Recursive merges show where the branch was from. Sometimes the fast forward merges is not easy to see from the merged branch.
When fast forward merges are not wanted but will happen, is possible to mark them explicitly for that:
$ git log --oneline --all --graph --decorate
* 282f1cc (HEAD -> my_account) Added my account css
* 2373699 Added my account page
* 1f2a155 (master) Merge branch 'categories'
|\
| * d5853d8 Added categories
* | 43b37e8 Commited products page
|/
* 6c863ad Added search page
$ git merge --no-ff my_account
Merge made by the 'recursive' strategy.
account.css | 0
account.html | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 account.css
create mode 100644 account.html
- This will happen when two branches or more modify the same files. There cannot be fast forward for this cases.
$ git lg * af67ff0 (master) Merge branch 'homepage_redesign' |\ | * d9ee191 Implemented home page redesign |/ | * abbbdac (HEAD -> cart) Added link on home page for shopping cart | * 48e6bf3 Added shopping cart |/ $ git merge cart Auto-merging home.htm CONFLICT (content): Merge conflict in home.htm Automatic merge failed; fix conflicts and then commit the result.
- When merging conflicts,
git status
is your friend, it tells us where we are at and what we need to do. The unmerged path has to be fixed before the commit. Git only needs a text editor for it$ git status On branch master Your branch is ahead of 'origin/master' by 18 commits. (use "git push" to publish your local commits) You have unmerged paths. (fix conflicts and run "git commit") Changes to be committed: new file: cart.html Unmerged paths: (use "git add <file>..." to mark resolution) both modified: home.htm $ vim home.htm <<<<<<< HEAD Company Logo! Links: - Products - Categories Copyrigth 2016 ======= link to cart >>>>>>> cart
- The equals shows the different sides and the branch where is different. Don't add stuff in merges, just resolve them!
- To resolve, use
git add .
$ git add . $ git status On branch master Your branch is ahead of 'origin/master' by 18 commits. (use "git push" to publish your local commits) All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: new file: cart.html modified: home.htm $ git commit
- To resolve, use
- The equals shows the different sides and the branch where is different. Don't add stuff in merges, just resolve them!
-
git diff
allows to see the differences of modified files. -
git help diff
gives the usage of the command (or any other git command) -
For example, if some changes happen in
home.htm
$ git diff diff --git a/home.htm b/home.htm index ea50146..db1180d 100644 --- a/home.htm +++ b/home.htm @@ -5,7 +5,7 @@ Links: - Categories - Cart - About +- History - My Account -- Checkout
-
git diff
shows only unstaged changes, for staged changes usegit diff --staged
-
git diff HEAD
shows the difference between the working directory and the last commit made (unstaged/staged changes, since there can be staged and unstaged changes on the same file)$ git s MM home.htm $ git diff --staged diff --git a/home.htm b/home.htm index ea50146..db1180d 100644 --- a/home.htm +++ b/home.htm @@ -5,7 +5,7 @@ Links: - Categories - Cart - About +- History - My Account -- Checkout Copyrigth 2016 $ git diff diff --git a/home.htm b/home.htm index db1180d..188179d 100644 --- a/home.htm +++ b/home.htm @@ -1,9 +1,6 @@ Company Logo! Links: -- Products -- Categories -- Cart - About - History - My Account $ git diff HEAD diff --git a/home.htm b/home.htm index ea50146..188179d 100644 --- a/home.htm +++ b/home.htm @@ -1,11 +1,8 @@ Company Logo! Links: -- Products -- Categories -- Cart - About +- History - My Account -- Checkout Copyrigth 2016
Rebasing is an intermediate tool to improve the quality of the experience when collaborating. Two things use rebasing in git, they should be treated differently because they are made for different things:
-
git rebase
: Change the starting point of the branch (base) before making merges -
git rebase -i
(interactive): Rewriting history to change order of commits, squash together or clean up for sharing with other people
Assume two feature branches
$ git lg
* 6ffc391 (feature2) Added feature2
| * bece78a (feature1) Added feature1
|/
* 23ff48b (HEAD -> master) Changed homepage links
After merging one, instead of keeping both feature branches, we can rebase feature2
(the starting point) for it to appear in the history after feature1
. The base of feature 2
is 23ff48b Changed homepage links
:
* 8e48a0e (HEAD -> master) Merge branch 'feature1'
|\
| * bece78a Added feature1
|/
| * 6ffc391 (feature2) Added feature2
|/
* 23ff48b Changed homepage links
We want to rebase it so it appears in 8e48a0e (HEAD -> master) Merge branch 'feature1'
. To do that:
$ git checkout feature2
Switched to branch 'feature2'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Added feature2
$ git lg
* dcd08f7 (HEAD -> feature2) Added feature2
* 8e48a0e (master) Merge branch 'feature1'
|\
| * bece78a Added feature1
|/
* 23ff48b Changed homepage links
* b249d89 Merge branch 'checkout'
This will 'undo' the work of feature2
, move to the HEAD of master and then redo the work using that as the base. The merge from feature2
to master
can occur then.
Assume 2 branches with conflicting changes. Merge one into master and the second one will create a conflict. The question is to whether rebase or merge the conflict. Fortunately is resolved the same. The merge conflict looks like this:
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Featuring el cuatro
Using index info to reconstruct a base tree...
M home.htm
Falling back to patching base and 3-way merge...
Auto-merging home.htm
CONFLICT (content): Merge conflict in home.htm
error: Failed to merge in the changes.
Patch failed at 0001 Featuring el cuatro
The copy of the patch that failed is found in: .git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Note the line When you have resolved this problem, run "git rebase --continue".
instead of suggesting git commit
. Git status will tell us what to do:
$ git status
rebase in progress; onto e1215af
You are currently rebasing branch 'feature4' on 'e1215af'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: feature4.html
Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: home.htm
After the conflict resolution, the merge can continue with git rebase --continue
:
$ git add .
$ git status
rebase in progress; onto e1215af
You are currently rebasing branch 'feature4' on 'e1215af'.
(all conflicts fixed: run "git rebase --continue")
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: feature4.html
modified: home.htm
$ git rebase --continue
Applying: Featuring el cuatro
cmurphy@cmurphy-pc ~/Documents/Projects/web1 $ git lg
* 85fa1d9 (HEAD -> feature4) Featuring el cuatro
* e1215af (master) Merge branch 'feature3'
|\
| * fc45c92 link to feature 3
| * e9b6c22 feature 3
-
Rename your local branch. If you are on the branch you want to rename:
$ git branch -m new-name
If you are on a different branch:
$ git branch -m old-name new-name
-
Delete the old-name remote branch and push the new-name local branch.
$ git push origin :old-name new-name
-
Reset the upstream branch for the new-name local branch. Switch to the branch and then:
$ git push origin -u new-name