Discovery Exercise on Git for Beginners

There are many online training for git

and many docs

Question 1 : Discovering local repositories

Open a shell terminal, create a new directory, change dir into it

$ mkdir tp-git
$ cd tp-git

Verify that git command does not detect any local repository

$ git status
fatal: Not a git repository (or any of the parent directories): .git

Initialize a new local git repository

$ git init
Initialized empty Git repository in /home/arnaud/tp-git/.git/

Check git repository status:

$ git status
Initialized empty Git repository in /home/arnaud/tp-git/.git/

Explore the (hidden) content of the directory:

$ ls

$ ls -a
.  ..  .git

$ find .
.
./.git
./.git/config
./.git/info
./.git/info/exclude
./.git/objects
./.git/objects/info
./.git/objects/pack
./.git/HEAD
./.git/description
./.git/hooks
./.git/hooks/pre-applypatch.sample
./.git/hooks/pre-commit.sample
./.git/hooks/applypatch-msg.sample
./.git/hooks/post-update.sample
./.git/hooks/update.sample
./.git/hooks/prepare-commit-msg.sample
./.git/hooks/pre-push.sample
./.git/hooks/commit-msg.sample
./.git/hooks/pre-rebase.sample
./.git/branches
./.git/refs
./.git/refs/heads
./.git/refs/tags

Read the .git/config file … nothing special yet

$ cat ./.git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true

Configure your git global settings

git config --global user.name <<YourFirstname Lastname>>
git config --global user.email <<yourfirstname.lastname@gmail.com>>

Add Some basic Alias

git config --global alias.st status
git config --global alias.ci commit
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.lol "log --graph --decorate --pretty=oneline --abbrev-commit --all"
git config --global alias.oneline "log --pretty=oneline --abbrev-commit --graph"

Example of alias and global setting son my account

$ git config --global -l

user.email=arnaud.nauwynck@gmail.com
user.name=Arnaud Nauwynck
push.default=simple
alias.st=status
alias.df=diff
alias.co=checkout
alias.ci=commit
alias.br=branch
alias.who=shortlog -sne
alias.oneline=log --pretty=oneline --abbrev-commit --graph
alias.lol=log --graph --decorate --pretty=oneline --abbrev-commit --all
alias.changes=diff --name-status
alias.dic=diff --cached
alias.diffstat=diff --stat
alias.lc=!git oneline ORIG_HEAD.. --stat --no-merges
alias.addm=!git-ls-files -m -z | xargs -0 git-add && git status
alias.addu=!git-ls-files -o --exclude-standard -z | xargs -0 git-add && git status
alias.rmm=!git ls-files -d -z | xargs -0 git-rm && git status
alias.mate=!git-ls-files -m -z | xargs -0 mate
alias.mateall=!git-ls-files -m -o --exclude-standard -z | xargs -0 mate
alias.undo=git reset --soft HEAD^

These settings can also be viewed/edited directly in text file ~/.gitconfig:

$ cat ~/.gitconfig
[user]
	email = arnaud.nauwynck@gmail.com
	name = Arnaud Nauwynck
[push]
	default = simple
[alias]
    st = status
    df = diff
    co = checkout
    ci = commit
    br = branch
    who = shortlog -sne
    oneline = log --pretty=oneline --abbrev-commit --graph
    lol = log --graph --decorate --pretty=oneline --abbrev-commit --all
    changes = diff --name-status
    dic = diff --cached
    diffstat = diff --stat
    lc = !git oneline ORIG_HEAD.. --stat --no-merges
    addm = !git-ls-files -m -z | xargs -0 git-add && git status
    addu = !git-ls-files -o --exclude-standard -z | xargs -0 git-add && git status
    rmm = !git ls-files -d -z | xargs -0 git-rm && git status
    mate = !git-ls-files -m -z | xargs -0 mate
    mateall = !git-ls-files -m -o --exclude-standard -z | xargs -0 mate
    undo = git reset --soft HEAD^

Question 2 - discovering clone remote repositories

To compare with a remote repository clone, open another shell terminal,

$ git clone https://github.com/praqma-training/gitkatas
$ cd gitkatas

Read the .git/config file …

$ cat ./.git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = https://github.com/praqma-training/gitkatas
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

Listing all the “remote” can also be done using command line:

$ git remote show
origin

$ git remote show origin
* remote origin
  Fetch URL: https://github.com/praqma-training/gitkatas
  Push  URL: https://github.com/praqma-training/gitkatas
  HEAD branch: master
  Remote branches:
    figaw-patch-1 tracked
    master        tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

Question 3 - git add, git commit

Save some files, add them to git, and commit them

$ echo "test" > file1.txt
$ git status
On branch master

Initial commit

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

	file1.txt

nothing added to commit but untracked files present (use "git add" to track)

Add your file content to git:

$ git add file1.txt
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   file1.txt

Commit your files

$ git commit -m "initial commit"
[master (root-commit) 865fda9] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 file1.txt


$ git status
On branch master
nothing to commit, working directory clean

Modify again your file

echo " -version2" >> file1.txt 
$ git st
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:   file1.txt

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

Question 4 - diff, browse history, undo local modification, compare revision, undo commit

add more commits:

 for i in 1 2 3 4 ; do echo $i >> file1.txt; git add file1.txt; git ci -m "add text $i"; done
[master 5e35789] add text 1
 1 file changed, 2 insertions(+)
[master c54c9c7] add text 2
 1 file changed, 1 insertion(+)
[master 8cb4301] add text 3
 1 file changed, 1 insertion(+)
[master f17cf73] add text 4
 1 file changed, 1 insertion(+)
$ git log
commit f17cf73e873543e32c740dfb2702bc041644bda4
Author: Arnaud Nauwynck <arnaud.nauwynck@gmail.com>
Date:   Sat Sep 30 05:57:06 2017 +0200

    add text 4

commit 8cb430127ae075b7c0ac15c22e1ed1be41f30a31
Author: Arnaud Nauwynck <arnaud.nauwynck@gmail.com>
Date:   Sat Sep 30 05:57:06 2017 +0200

    add text 3

commit c54c9c7635e9d729f9664b0180d0463631242ca9
Author: Arnaud Nauwynck <arnaud.nauwynck@gmail.com>
Date:   Sat Sep 30 05:57:06 2017 +0200

    add text 2

commit 5e3578944d01b6562d585a305f9d1fcc5daae56c
Author: Arnaud Nauwynck <arnaud.nauwynck@gmail.com>
Date:   Sat Sep 30 05:57:06 2017 +0200

    add text 1

commit 865fda9ed4860fb47e196d6fa68a9afd4a0b81ff
Author: Arnaud Nauwynck <arnaud.nauwynck@gmail.com>
Date:   Sat Sep 30 05:26:44 2017 +0200

    initial commit

See also

$ git lol 
* f17cf73 (HEAD -> master) add text 4
* 8cb4301 add text 3
* c54c9c7 add text 2
* 5e35789 add text 1
* 865fda9 initial commit

$ git oneline  # idem.. (no branches yet)

Do a local un-committed change:

$ echo "temporary-change" >> file1.txt
$ git status

$ git diff 
diff --git a/file1.txt b/file1.txt
index e685709..bf1f340 100644
--- a/file1.txt
+++ b/file1.txt
@@ -4,3 +4,4 @@ test
 2
 3
 4
+temporary-change

Undo local uncommitted change:

$ git checkout HEAD -- file1.txt
$ git status

Re-checkout file content from previous commit:

$ git co c54c9c7 -- file1.txt

compare with (equivalent?):

$ git co HEAD^^ -- file1.txt
$ git co HEAD~~ -- file1.txt
$ git co HEAD~{2} -- file1.txt
$ git co master^^ -- file1.txt

Amend a commit to change it (change content files, or change comment)

$ git commit --amend -m "changed comment"

Undo a commit (dangerous rewrite…)

$ git reset HEAD^
$ git lol
* 8cb4301 (HEAD -> master) add text 3
* c54c9c7 add text 2
* 5e35789 add text 1
* 865fda9 initial commit

$ git reset HEAD^
$ git lol
* c54c9c7 (HEAD -> master) add text 2
* 5e35789 add text 1
* 865fda9 initial commit

Question 5 - branch, merge

Create a local new branch, switch to this new branch

$ git branch
* master

$ git branch branch1
$ git branch
  branch1
* master

$ git co branch1 
Switched to branch 'branch1'
$ git branch
* branch1
  master

Do some modification in branch1:

$ echo "modif on branch1" >> file1.txt 
$ echo "new file on branch1" > file2.txt
$ git add .
$ git ci -m "modif file1.txt and added file2.txt on branch1"
[branch1 2d25a1d] modif file1.txt and added file2.txt on branch1
 2 files changed, 2 insertions(+)
 create mode 100644 file2.txt

$ git lol 
* 2d25a1d (HEAD -> branch1) modif file1.txt and added file2.txt on branch1
* c54c9c7 (master) add text 2
* 5e35789 add text 1
* 865fda9 initial commit

Now switch back to branch master, check no modifications from branch1 are present

$ git co master
Switched to branch 'master'

$ git st
On branch master
nothing to commit, working directory clean
$ ls
file1.txt
$ cat file1.txt 

Then merge changes from branch1 to this branch (master)

$ git merge branch1 
Updating c54c9c7..2d25a1d
Fast-forward
 file1.txt | 1 +
 file2.txt | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 file2.txt

$ ls
$ cat file1.txt 

Repeat Same question… but do simultaneously changes on “branch1” and “master” before merging (on separate file names, so not causing conflicts)

before merge:

$ git lol
* f9d1431 (HEAD -> branch1) change branch1
| * b82a66d (master) change master
|/  
* 2d25a1d modif file1.txt and added file2.txt on branch1

after merge:

$ git lol
*   2571f53 (HEAD -> master) Merge branch 'branch1'
|\  
| * f9d1431 (branch1) change branch1
* | b82a66d change master
|/  
* 2d25a1d modif file1.txt and added file2.txt on branch1

Question 6 - Create your own Github account, and repository

go to https://github.com Create an account, then create a repository “csid-exercises”

clone on your local PC your new github repository:

$ cd cours
$ clone https://github.com/<<your-account>>/csid-exercises

Question 7 - Create a github private key

Go in https://github.com settings menu
Then go in sub-section for SSH and GPG Keys

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Then add it to your github account (add public key part… keep private key secret)

There is a doc at bottom of page: Learn how to generate SSH keys

Notice you could retype your password when pushing commits to github if you don’t have your private key on a PC.

Question 8 - Commit and Push to Github

Commit and push files to your new “csid-exercises” github repository

Save the commands you typed for these exercises as a text file “csid-exercises/tp-git/tp.txt”

Also add a short description markdown file for this repo: “csid-exercises/README.md”

$ git add README.md
$ git add tp-git/
$ git commit -m "initial commit"
$ git push

Setup a second local clone of the same remote repository. Try pull/fetch/push …

$ cd ~/cours
$ git clone https://github.com/<<your-account>>/csid-exercises  csid-exercises2
$ cd csid-exercises2
$ git pull 
$ echo ".." >> ftp-git/file1.txt; git add .; git ci -m "update"; git push  

.. 
$ cd ~/cours/csid-exercises
$ git pull 

Question 9 - discovering Gitkatas

$ git clone https://github.com/praqma-training/gitkatas
$ cd gitkatas
$ ls
$ cd basic-commits
$ ls
$ gedit README.md&
$ . ./setup.sh

Question 10 - testing merge conflict, using Gitkatas

example of a gitkatas exercise on resolving conflicts:

$ cd gitkatas/merge-conflict
$ gedit README.md &
$ . ./setup.sh
$ cd exercise

You have to merge branch “merge-conflict-branch1” to branch “master”, but there is a conflict on file…

You must solve it to get this result:

arnaud@arn:~/gitkatas/merge-conflict/exercise$ git lol 
*   f68e64f (HEAD -> master) merged
|\  
| * 71cae00 (merge-conflict-branch1) add relevant fact
* | 0fcabd5 add indispensable truth!
|/  
* ed4face Add content to greeting.txt
* 806d0b8 Add file greeting.txt