Wednesday, March 31, 2021

Git - introduction

 
$ git version
$ git init

.git stores config files

$ mkdir git-repo
you are on master branch by default
lets rename

$ git branch -m main

branch master renamed to main

$ git branch


create a new repo
$ git init

create files in your local repo

Git object types
blob - represent files
tree - represents folder/directory
commit    - actual pointers to trees.
    - You can create different commit.
    - So, you can create different pointers to different trees.
    - With the help of commit, you can create different snapshot of your project at different time.
    - With checking out different commit, you can go back in time with historical versions in the git repository.

annotated Tag

Hash
- hash is unique identifier of every git object in git repository.
- hash is created using specific hash function namely SHA1 hash function.
- hash function creates fixed length hash function.
- it can take any variable length input
   what it mean is that we can have content of large file, and apply it hash function and as a result, we get a fix length hash.
- hash represents in hexadecimal characters.
- in the hash, you will see ABCDEF




variable length input

Any variable length input

hash function

A2333B7C9D088F766E68D888D9697

fixed length hash


In hexadecimal, there are 16 different characters: 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

Decimal format -> 10 characters (0,1,2,3,4,5,6,7,8,9)

Binary format -> 2 characters (0,1)

as we know hash is unique identifier, every object in git.

it is SHA1
- It creates 160 bits long
or
- 40 hexadecimal characters


Staging Area
Lets create a file in repo

$ echo "First line" > myfile.txt
$ ls -l; cat myfile.txt


$ echo "Line1" >1.txt
[sam@master git]$ cat 1.txt
Line1
[sam@master git]$

In git, there are three areas where files and folders can be located.
- Working Directory
- Staging area (index)
- Git repository

Working directory
- It is a folder where you keep your files
In our case, where 1.txt is located, is the working directory
[sam@master git]$ pwd
/home/sam/git

Staging Area (Index)
- it is an intermediate area, between working area and git repository.
- Before copying files from working directory to git repo, files must be placed in staging area or index.
- When you check out specific files from git repo, they moved through staging area into working directory.
- So it is an intermediate area between working area dn git repo (local)

Git Repository
- It is a hiddern folder at the working directory - .git
- You can verify if our file 1.txt is on repo or not by typing the command
[sam@master git]$ ls .git/objects/
2b  3b  3d  3f  55  62  87  d2  e1  info  pack

when you commit the change to this repo, you will see the object (file) added to the repo.


How can you move files from staging area to working area and from staging area to git-repo?
Here is a work flow,

 working area        Staging area        Git repo
|-----------        ------------        ---------
|--------> Stage ------> |
|    git add
|             | -----> Commit ---------> |
|                git commit -------> |
|                            |
|     jump into certain "version" of the project    |
| <----------- git Checkout ------------------------|


Add files from working area to staging area.
- Run the command 'git add'
- This command requires arguement.
- if you specify . as an arguement, it will add all changed or untracked files into staging area or the index.
- But this command does not put files on the git-repo.

Adding files from staging area to git repo.
- Run command 'git commit'
- This command takes files from staging area, files that are staged, place them in git-repo.
- Creates coresponding objects at the .git/object directory.
- After git commit, git creates 'commit' object.
- This object also has unique hash,

coping files from git repo to working directory.
- After you commit the changes at staging area, git commit creates an object called hash which will allow us to check out different commit using command 'git checkout'.
- Using this command, you can just between different versions of your project.
- When you run 'git checkout' command, files are folders are copied from git repo, goes throug staging area, and applies into working area.
- That means, after git checkout command, context of working directory are changed.

now, lets go throug the LAB,

[sam@master git]$ cat 1.txt
Line1

[sam@master git]$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

 1.txt

nothing added to commit but untracked files present (use "git add" to track)
[sam@master git]$

Here,
- we are working on branch master, and there are not commits yet.
- Under untracked files section, we see file 1.txt.
- This file is not tracked by git. and it does not track the changes on this file.
- You can mofidy this file, add, remove content, rename it, it will still remain untracked.
  all the changes are not being saved in git-repo so incase you want the modifed content back, you
  you can't get it since its not tracked.
- Now, lets move this file to staging area, using comand git add. after add you can specify name of the file
$ git add 1.txt
$ git status
you will see that there are changes to be committed.
- you see there is one file called 1.txt located in staging area of the index.
- Now, this file is ready for commit.
- Now we can use 'git commit' command in order to commit (save) the changes.
- Lets not yet commit the change at the moment. Let the file be in staging area.

Now, lets talk about commit
- When you commit changes, git automatically adds information about commit author name and email.
- This information is stored on all commit object.
- Every commit object in git, any object has a SHA1 hash.
- Below you see part of has characters of SHA1 hash of the commit object.
- Every commit has author name and email.

As we know git works locally on your computer.
- if you want to attach your name and email, you have to configure them in git settings.
- Each commit has author, email along with description and pointer to the parent commit, commit that was created before.
- This means that all commits are chain. Every new commit points to parent commit.
- Every commit might have one or two or more parents.

6b4jan  commit
auther name and email
commit description
parent

Now, lets configure author name and email
$ git config --global user.name <Name>
$ git config --global user.email <email>
$ git config --list

[sam@master git]$ git config --global user.name "Kay"
[sam@master git]$ git config --global user.email "gofairfax@gmail.com"
[sam@master git]$ git config --list
user.email=gofairfax@gmail.com
user.name=Kay
color.ui=true
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true

These commands set author name and email globally.
before making chanes, verify with git config --list


Now, lets go ahead and commit the change using the command git commit
- This will commit changes that are allocated in staging area
- After commit, the working directory, staging area and git-repo will be synchronized.
- What that mean is that our file 1.txt will be present in all areas.

lets commit changes

[sam@master git]$ git status
On branch master
No commits yet
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
 new file:   1.txt
[sam@master git]$

we see, 1.txt is ready to be committed.

Note: Every commit requires message, so use flag -m to add message
[sam@master git]$ git commit -m "First commit"
[master (root-commit) 69000f0] First commit
 1 file changed, 1 insertion(+)
 create mode 100644 1.txt
[sam@master git]$

you see, your commit is created from the output.
- You see the hash value from committed object.
- author and email is also available
- You also see that 1 file is changed.
- There is one line, one insertion added to the file.

Git status
- now run the command 'git status'

[sam@master git]$ git status
On branch master
nothing to commit, working tree clean

you see a message that there is nothing to commit. tree clean.
- this means all areas are synchronized.

git branch
- Now type a command 'git branch'
- you will see name of the branch on the list. the branch currently checkedout branch, where we are currently working - master in my case.
- All current commit are committed in this branch.

[sam@master git]$ git branch
* master

This is our currently checked out branch.


=> Commit history
Lets check the commit history.
to see all commit, run git log

[sam@master git]$ git log
commit 69000f0b693f0a92d23fa044020df99879f1f150 (HEAD -> master)
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 08:53:15 2021 -0400

    First commit
[sam@master git]$

we see only one commit here.
You can see full hash commit object id.
main branch, pointer of the branch: master.

it points to last commit.
we see author name, email and date along with message.

You also see a pointer HEAD  (Upper case) which points to main branch.
This main branch now points to the commit sha1 hash.

Hash is actually a dynamic pointer. It represents your current location.

At the moment, we are at the master branch. HEAD points to Master branch.

if there are multiple branches, you can easily move between different branches.
by using the checkout other branch.

- When you check out specific branch, what actually git does is moves the HEAD pointer to other branch (New Branch).

- Same applies when  you checkout specific commit.
- we can not checkout specific commit since we only have one branch.
- When we create another file, and another commit, we will be able to checkout specific commit and hash will move out to specific commit.

Now, lets create a file in working directory and perform the similar actions at staging ara and commit the change.

lets create a file.

[sam@master git]$ cat > 2.txt
File 2
[sam@master git]$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

 2.txt

nothing added to commit but untracked files present (use "git add" to track)
[sam@master git]$


We see untracked files.  2.txt

lets add this file to staging area and commit changes.

you can use git add . to save all chages to staging area.

[sam@master git]$ git add .
[sam@master git]$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

 new file:   2.txt

you can see changes to be commmited.

now, change the commit.
[sam@master git]$ git commit -m "2nd file"
[master a4552f4] 2nd file
 1 file changed, 1 insertion(+)
 create mode 100644 2.txt

see you can see + sign which tells you new line is inserted.

if you modify the existing file, you may see - sign.

file is commited. lets see the status
[sam@master git]$ git status
On branch master
nothing to commit, working tree clean

it says clean.

Now lets see the output of git log command.
[sam@master git]$ git log
commit a4552f4dff721ea23ca32d62fb507e2899d61a67 (HEAD -> master)
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 12:09:31 2021 -0400

    2nd file

commit 69000f0b693f0a92d23fa044020df99879f1f150
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 08:53:15 2021 -0400

    First commit

now, we see two commits. new commit on the top. we see unique SHA hash.

Note, the HEAD is point to master and point to laster commit.

This means, git automatically moves branch pointers to the last commit that you made.

HEAD is a dynamic pointer. It also moved along with branch.
Infact HEAD still points to master branch.
it does not know that there is a new commit. Because it only points to the branch.
Branch pointer actually changed.
Now, it points to new commit hash instead of old hash.

We know, on old commit, file 2 does not exists.
if you check out this commit, using the old hash, you will not find file2.
You will only see old filen not the new one.


Some basic git commands
-----------------------

1. git status    
- Shows you the current state of git repository.
- Shows you what files are tracked, modified
- if all three areas are on sync, you will see a message "there is no changes to commit message."

2. git add        
- You can add files to staging area or index
- This means moving files to staging area before you commit.

3. git commit    
- git commit writes actual changes to git repository
- It creates new git commit object
- This object contains information such as author name, email, commit messages, and date

4. git log        
- With 'git log' command you can read the history of changes (commits)
- The moment our git repository, there are two different types of commit.
- In each output, there is such information as SHA hash of every commit object, author name, email, date of the commit and commit message.
- It also shows current branch name and pointer to specific commit.
- Usually, branch points to the last commit made in the git repository.

4. git cehckout    
- Using this command you can checkout specific commit by each SHA hash or branch by using branch name.
- Now we have two different commits.
- Using git checkout, we can move files from git repo to working directory.
- git checkout updates your working directory.



Checking out, commits, and branches
----------------------------------
Lets checkout specific commits.

[sam@master git]$ git status
On branch master
nothing to commit, working tree clean
[sam@master git]$ git log
commit a4552f4dff721ea23ca32d62fb507e2899d61a67 (HEAD -> master)
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 12:09:31 2021 -0400

    2nd file

commit 69000f0b693f0a92d23fa044020df99879f1f150
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 08:53:15 2021 -0400

    First commit
[sam@master git]$

[sam@master git]$ ls
1.txt  2.txt


We see two files here.
Now, lets do git checkout to previous commit.
- the first one, file 2.txt will disappear.

lets copy the old hash and do the git checkout.
- You can copy first 6 hash characters rather than whole
so, we types git checkout and part of hash

[sam@master git]$ git checkout 69000f
Note: checking out '69000f'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 69000f0 First commit
[sam@master git]$

- You see checking out to hash.
- You have detached HEAD.
- At the end of the output, you see HEAD is now at old hash 69000f0.

read all the message on the screen to understand more.

Lets list the files on the working directory.

[sam@master git]$ ls
1.txt
[sam@master git]$

now, we see only one file.

when you checkout specific commit or branch, you actually moved to another state of the repository.
- We just moved to the previous state of the repository.
- At the moment there is not 2.txt file.

Lets check the log

[sam@master git]$ git log
commit 69000f0b693f0a92d23fa044020df99879f1f150 (HEAD)
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 08:53:15 2021 -0400

    First commit
[sam@master git]$

we see only single commit.
- See the HEAD - dynamic pointer points to the specific commit hash.
- There is no branch here.
- Branch may still exists, 2nd commit still exists. We can go back to 2nd commit.
- The branch points to the 2nd commit thats why we can't see it here.

Thats why we have to checkout specific branch, not the commit.
if you have to check out specifc branch, you simply enter 'git checkout <branch_name>

[sam@master git]$ git checkout master
Previous HEAD position was 69000f0 First commit
Switched to branch 'master'
[sam@master git]$


Now, I am on branch master.
Look at the message,
- Previous HEAD position was 69000f0.
Now, switched to branch master
now, list the files.

[sam@master git]$ ls
1.txt  2.txt

Now, you see 2nd file as well.

Now, you move to a different state of the repository.

now, run 'git log'

[sam@master git]$ git log
commit a4552f4dff721ea23ca32d62fb507e2899d61a67 (HEAD -> master)
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 12:09:31 2021 -0400

    2nd file

commit 69000f0b693f0a92d23fa044020df99879f1f150
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 08:53:15 2021 -0400

    First commit
[sam@master git]$

You see two commits now.
latest commit points to the master branch.

This way, you can go back to different commits and differetn branches. And find your old data files.

We just checkout commit, branches by its name.


File Tracking status in Git
---------------------------
There are 4 of them
1. Untracked
2. Unmodified
3. Modified
4. Staged

Untracked
- When we create a new file at working directory
-

Unmodified
- Lets run the status command
[sam@master git]$ git status
On branch master
nothing to commit, working tree clean

= here, you see nothing to commit message. There is no change in file to be commited.

Modified
Lets modify file 1.txt

[sam@master git]$ cat >1.txt
Line2
$ cat 1.txt
Line 1
Line2

[sam@master git]$ git status
On branch 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:   1.txt

no changes added to commit (use "git add" and/or "git commit -a")

Notice, we see different status.
we see modified file. and the file.
before both files were no tracked by git but now its tracked by git and say modified.

Staged
- When file is moved to the staging area.


Git commit command,
[sam@master git]$ git status
On branch 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:   1.txt

no changes added to commit (use "git add" and/or "git commit -a")
[sam@master git]$

lets commit it
[sam@master git]$ git commit -a -m "Change to the first file"
[master 921d70b] Change to the first file
 1 file changed, 1 insertion(+)
[sam@master git]$

-a - add -> files will be automatically added to the staging area before making actual commit.
-m -> commit message
 
Here you see the name of the Branch 'master' where we made this commit and with the sha hash
2nd line shows the change made to commit file.
1 file changed , 1 lines (insertition) but there is no deletion.

Now, git status shows nothing to commit.

[sam@master git]$ git status
On branch master
nothing to commit, working tree clean
[sam@master git]$ cat 1.txt
Line 1
Line2

we see the containt of file 1.txt with updated information.
[sam@master git]$ git log
commit 921d70b68bedbbcd28a681b75e75840f50dfa71a (HEAD -> master)
Author: Kay <gofairfax@gmail.com>
Date:   Fri Apr 2 16:54:43 2021 -0400

    Change to the first file

commit a4552f4dff721ea23ca32d62fb507e2899d61a67
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 12:09:31 2021 -0400

    2nd file

commit 69000f0b693f0a92d23fa044020df99879f1f150
Author: Kay <gofairfax@gmail.com>
Date:   Thu Apr 1 08:53:15 2021 -0400

    First commit
[sam@master git]$

You see three commit hash.
latest one on the top.

Branch pointer moved auotmatically moved to the last commit.
HEAD points to master branch.

if you go from top to buttom, the oldest commit (69000f0) is parent to a4552f and a4552f is parent to 921d70b.

You see the order. this shows the parents of the specific comit.


17. Branch and merging branches

Lets say,
- We have branch master, and several commits in the project called root commit.
- We also have two featured branches called feature1 and feature2.
- These brances are created from the master branch at different moment of time.
- The feature1 of branch is creaed at earlier time. ADter that there are other commits
- Feature1 branch has a1, a2, a3 .. commits.
- First commit on feature1 branch has commit 2 as a parent
- Feature2 branch is created little later with a different commit.
- So, feature1 and feature branches are two seperate lines of the story.
- We have master soty and we have other two feature stories.
- Normally, feature branches are created when you want to develop a particular feature.
- You have to test specific feature, and when you are ready, you have to merge specific feature into the main (Master) branch.
- Main branch (Master) can be any name not necessarily a master branch.
- But the main idea is to merge the feature branches into the master branch.


        1   2  3  4  5  6  7  8  9
root commit -   -  -  -  -  -  -  - -
        |     |     | master (HEAD)
        |     |
        |     ---b1--b2--b3---- (Feature2)
        |
        |
        --a1--a2--a3-- (Feature1)


So, how the merge works?

Here are  the merging process.
1. Create a new feature branch from the master (main) branch.
2. Make changes in the new feature branch and commit the change.
3. Checkout master (main) branch (The one where you are going to merge the feature branch)
4. Merge the feature branch to the current receiving branch.

$ git merge <feature-branch>

Note: You can also merge multiple branches at the same time. It is a good idea to merge single feature branch.


What happens when you perform merge?

Three way merge,
- Lets say there is a master branch and one feature brance is created.
- New feature branch has some commits and also master branch also has some commits.
- What we will do is that we will commit at one point where we perform a commit which is common to feature and main branches.
- Once we decided to merge feature branch and master branch, it will create a new merge commit.
- Now, the receiving branch (master) that had some commits, that were not available on feature branch, are now available on merge commit (Master).
- When git does this kinds of commits, git will have two parents.
  - One from main commit and another is from feature commit.
- Once branch is merged, you can safely remove the feature branch.
- But all the feature commits will be kept safe because they are pointer to the commit (Pointer from merge commit).

There is another kind of merge is also called fast forward merge. It is applied when there are no additional commits in the receiving branch after creation of feature branch.
- But in reality, 90% of the time, 3 way merge is applied.

Note: before the master (main) branch pointer, it was pointing the the previous pointer on master branch.

After merging, main branch  pinter moves to the last commit in the main branch (Merge commit).

HEAD moves along with main(master) branch.

Note: Git does not create merge commit, it just moves the pointer of the receiving branch to the last commit in the feature branch. But such method is possible only when there are no other commits after ancestor commit in the receiving branch.


Branch merging in action
------------------------
Lets get hand dirty
Plan:
1. Create a feature1 branch
2. Checkout feature1 branch
3. Create a new file file1.txt and commit it in the feature1 branch
4. Checkout master (main) branch
5. Create new file 2.txt and commit it in the main branch.
6. Merge feaure1 branch into the main branch
7. Delete feature1 branch



No comments:

Post a Comment

Git branch show detached HEAD

  Git branch show detached HEAD 1. List your branch $ git branch * (HEAD detached at f219e03)   00 2. Run re-set hard $ git reset --hard 3. ...