V e r s i o n    C o n t r o l    S y s t e m    Git

Brackets Example Meaning
Square [argument] Argument is mandatory.
Curly {argument} Argument is optional.
Round (argument) Argument is not part of the syntax but was inserted as an explanation.
Angle <argument> Argument is a variable to be replaced by a value.
Tab. Typographic conventions

  1. Motivation

    Before 2016, there was no acute need for a Version Control System (VCS).
    Internal implementation projects were merely feasibility studies: Only the final version of each implementation (branch) would be secured using the same standard backup procedure as for the rest of my data.
    Future projects might require a sophisticated maintenance of sources: They will include more sources, they will manage concurrent branches, they will possibly require cooperation between distant developers.

    I will not debate whether Git - compared to other VCS - is a better choice or why: I cooperate with developers who use Git extensively. Focus of this documentation are issues that I have (or will have) to solve in projects I will be involved in.

  2. Underlying Model

    In their book Pro Git Book, Scott Chacon and Ben Straub explain the model behind the Distributed Version Control System (DVCS) implemented in Git. If users bear it in mind, they will avoid misunderstandings or wrong handling. There are several conceptualization levels to explain a model. Scott Chacon and Ben Straub distinguish 2 levels:

    • A general level listing abstract characteristics of Git - say its general modelling principles
    • A more precise representation of features that should allow developers to come to theirs conclusions.

    1. General Characteristics

      1. Git considers data history as a stream of snapshots.
        Git does not store a list of file-based changes but rather view the data as a set of snaphots of a miniature file system. Every time you commit or save the state of project, Git takes a picture of what the files look like at that moment and stores a reference to that snapshot.

      2. If between two snapshots a file has not changed, Git just links to it (instead of storing the same data twice).

      3. Each Git repository stores the complete branching information locally.
        This is especially the case, if a team of developers cooperates remotely. Each part of the team may have a Git repository on their server that will be 'synchronized' from time to time. From the Git perspective, no repository is more important as any other.

    2. More accurate Description

      1. Git attributes to each controlled file one of the following state:

        1. committed: The file is safely stored in the (local) repository,
        2. modified: The file has been changed since the last commit,
        3. staged: The modified file will be included into the next commit.

      2. Git structures its git repository into 3 "trees":

        1. The working Directory
          holds actual project data/files (more exactly, it is a single checkout of one version of the project):
          Each file in the working directory can be either tracked or untracked.

          • Untracked files are ignored (not under source control).
          • Tracked are those files that were in the last snapshot: They can be unmodified, modified or staged.

        2. Meta-data index
          designates the staging area (Staged files are modified files to be included into the next commit(-object)).

        3. Meta-data HEAD
          is a pointer to the last commit-(object) of the current branch i.e. a pointer to the tip of the current branch.
          Note that in Git terminology a head (lower case) is a pointer to a tip of one branch: HEAD (upper case) simply designates the head of the current branch.

        The tree organization above as well as the fact that each local repository is a complete replication account for what seems to be additional user steps in order to secure changes - at least in comparison with some other source control programs.


        Fig. 1: Repository trees (source Roger Dudler)

        The repository structure above bases on the way how the Git designers perceive the software development process:

        1. A Developer changes/updates files.
        2. Git action add transfers state of file from changed to staged.
        3. Git action commit transfers state of file from staged to committed.

      3. Branching:
        Branching is a fundamental functionality of any VCS. Most development projects do not maintain a single (time) line, but rather concurrent versions of sources - the so-called branches - that may merge as the project progresses. According to S. Chacon and B. Straub, Git makes branching comparatively easy - lightweight - because of the manner it proceeds.

        When a content is staged:

        1. Git processes each modified file into a repository file called blob that is named after the checksum (SHA-1 hash) of associated content.

        When a content is committed:

        1. Git processes each subdirectory of the working area to a tree-file stored into the repository. A tree-file basically links the names of all source file in the subdirectory with their currently associated blob names. Tree-files are also named after the checksum of an associated content. (S. Chacon and B. Straub write: "Git checksums each subdirectory".)

        2. Git creates a commit-object containing following meta-data:

          • A pointer to each tree-file.
          • The author's name and his email
          • The commit message
          • Pointers to the predecessor commit-object(s): the so-called parent(s). Initial commit-objects have no parent. Commit-objects have several parents, if they result from a merge of two or more branches.

          As for blobs and tree-files, a commit-object is named after the checksum (SHA-1) of associated content.


          Fig. 2: Commit-object pointing to a snapshot (source git Chapter 3 by S. Chacon and B. Straub)

          Above, the simplified representation of the git repository tracking a project with only 3 data files README, LICENSE, test.rb.

          • The data files have been staged as blobs 5b1d3, 911e7, cba0a.
          • Since this project has no subdirectory, there is only one tree-file 92ec2 listing 3 pairs [blob (id)] [file (name)].
          • The commit-object 98ca9 points to tree-file 92ec2 representing the "project snapshot".

        As the project progresses, developers add successive commit(-objects): A development line is simply a chain of commits, pinpointing valuable stations as the project matures. Each commit points to a snapshot (to retrieve the content) and to its predecessor(s) (to retrieve the history).


        Fig. 3: Project development Line (source git Chapter 3 by S. Chacon and B. Straub)

        • Commit(-object) 98ca9 the initial commit-object points to the original snapshot of project A (allowing to retrieve the state of the working directory as the repository was initiated).
        • Next commit(-object) 34ac2 points to the next snapshot of project B. It also points to its parent commit 98ca9 and so on.

        The development line shown above is obviously the main development line - since it begins with initial commit 98ca9.


        Fig. 4: Main development line is branch master (source git Chapter 3 by S. Chacon and B. Straub)

        Each development line - linear chains of commits - is associated with a branch-object, pointing to the last commit of that branch, its tip: A branch is identified by its branch-object. By default (unless the user explicitly decides otherwise) the main development line is associated with the Git branch named master.

        Fig. 4 shows the same project as in Fig. 3, at the development line level. The main line is a branch like any other - with the property that its first commit has no parent. By default, Git names the branch(-object) representing the main line master - master points to the last commit in the main line.

        Git knows which branch is currently activated by means of an additional pointer - more accurately a pointer to a pointer - called HEAD. Project displayed in Fig. 4 has only a main development line: HEAD points to master.

        Creating a branch (command branch) prompts Git to create a branch-object (that is essentially a pointer to a commit-object).
        If we assume that the repository state corresponds to Fig. 4, creating branch testing will create a branch-object pointing at commit-object f30ab (the active commit-object = current commit-object on the active branch).


        Fig. 5: Create branch(-object) testing (source git Chapter 3 by S. Chacon and B. Straub)

        Creating a branch does not switch to that branch: HEAD in Fig.5 still points to the (main) branch master (not to testing).

        HEAD must be explicitly redirected to branch testing (command checkout testing), before the developer can work on it (Fig. 6).


        Fig. 6: Switch to branch(-object) testing (source git Chapter 3 by S. Chacon and B. Straub)

        Let's assume a developer works on branch testing for a while and commits. The project state might be as displayed in Fig. 7.


        Fig. 7: Commit on branch testing (source git Chapter 3 by S. Chacon and B. Straub)

        Switching back to master is easy and fast: It only involves redirecting pointer HEAD to branch master - by means of command checkout master (Fig. 8).


        Fig. 8: Switching back to branch master (source git Chapter 3 by S. Chacon and B. Straub)

        Let's assume the developer performs changes on branch master and commits: The two branches master and testing have developed apart. The new situation might be depicted as in Fig. 9.


        Fig. 9: Branches master and testing after divergence (source git Chapter 3 by S. Chacon and B. Straub)

        The state of project as shown in Fig. 9 may be displayed using command git-log i.e. git log --oneline --decorate --graph --all displays following output.


        Fig. 10: git-log of divergent branches (source git Chapter 3 by S. Chacon and B. Straub)

  3. Installation

    For now, I am primarily concerned with the command line interface - which requires opening a Shell window (e.g. Bash) and call Git.

    Note: The command line interface is fully operational, as soon as Git has been installed. On my operating systems - whether Linux or OSX - Git is installed by default - into /usr/bin/git. (Type which git on the command line for verification)

    If Git is not already installed, several options to install it manually are available:

    Note: There are several GUI available that support different subsets of Git commands (Probably none of them will support the complete set).

  4. Configuration

    Git comes with a command called git config that allows to determine how it looks and operates. There are two kinds of arguments:

    1. Arguments defining actions to perform on those data: basically either read or write (key) values
    2. Arguments defining data (sources) (e.g. identifying the appropriate configuration file).

    A "configuration variable" is an ordered pair key value written in one single line of a file that Git recognizes as one of its configuration files.

    No. Configuration Level Description
    1 System

    • On my OSX computer, a system configuration file/private/etc/gitconfig was stored. The values stored here are valid by default for every user and repository. Use argument --system to target this file.
    • On my Linux system, there is no such file by default. Command (sudo) git config --list --system returns an error message that /etc/gitconfig does not exist.

    2 Global

    On my computer, the global configuration is stored in file <Root_Directory_Of_User>/gitconfig. Those values are specific to a user and his repositories. Use argument --global to target this file.

    3 Project

    Project configuration is stored in file <Root_Directory_Of_Repository>/.git/config.

    Tab. Configuration levels (from general to specific)

    Notes:
    • As would be expected, a more specific level overrides previous ones: configuration values attached to a project override for example those attached by default to a user.

    • The configuration file locations may change according to the operating system. For unixoid OS, such as MACOSX or my Linux OS , the correct location should be easy to infer. For Windows systems, the matter may be more difficult. To identify a location, the user shall try to edit the configuration values git config --edit at the level he wishes to operate. Git will try to check the appropriate configuration file - which may fail, if the user is not granted sufficient access rights.

    No. Command Description
    1 Git config (without argument)

    Action Display usage: If no argument is entered, the command displays its usage.
    Result: The list displays following categories:

    Category Key
    Config file

    --global use global config file
    --system use system config file
    --local use repository config file
    -f, --fileuse given config file
    --blob read config file from given blob object

    Action --get, --get-all, --get-regexp, --get-urlmatch,
    --replace-all,
    --add,
    --unset, --unset-all,
    --rename-section,
    --remove-section,
    -l, --list,
    -e, --edit,
    --get-color, --get-colorbool
    Type

    --bool, --int, --bool-or-int, --path

    Other -z, --null, --name-only, --includes, --show-origin

    Tab. Git Config Usage

    No. Command Description
    1 Git config --system -l
    Git config --system --list

    Action: Display system configuration values
    List all Git configuration variables set at the system level i.e. list key=value pairs, valid (by default) for all users and repositories.

    On my system, no variable is displayed, since file private/etc/gitconfig (that I created separately and moved subsequently) only contains comments (i.e. lines beginning with sign #).

    2 Git config --global -l
    Git config --global --list

    Action: Display global configuration values
    List all Git configuration variables set at the global level i.e. list key=value pairs valid (by default) for the user and his repositories.

    On my system, command reads file ~/.gitconfig and lists i.a. following key=value lines:
    user.name=Amar Khelil
    user.email=akh@khelil.de
    push.default=simple

    3 Git config --local -l
    Git config --local --list

    Action: Display local configuration values
    List all configuration variables set at the local level i.e. list key=value pairs valid only for the current Git repository.

    In order to display local values, git must know which repository is targeted and therefore the user must cd /to/git/repository beforehand.

    4 Git config -l
    Git config --list

    Action: Display current configuration values
    List all Git configuration variables known i.e. list key=value that Git can deduce.

    If the current directory is a repository, variables from all levels are displayed, from general to specific i.e. if a key appears several times the last value applies. If the current directory is not a repository, only system and global variables can be displayed (Git does not know about a specific repository).

    5 man git-config

    Action: lists all the available configuration options in detail.

    Tab. Display Git configuration values (Argument -l or --list)

    Note:

    • User name and email address (set at the --global resp. user level) are mandatory because Git uses them to identify commits. In other words, if keys user.name and user.email have not been automatically populated, the user must edit them (e.g. Git config --global --edit see next table)

    No. Command Description
    1 Git config --edit

    Action: Edit configuration variables
    Git opens one configuration file and the user can edit key value pairs (one pair for each line). Each configuration level has its associated file.

    If no argument is entered, Git assumes that the user wants to operate at --system level. It is recommended that the user always specify his preference: --system or --global or --local).

    Examples:

    • It is convenient to set a preferred editor (e.g. vi: git config --global core.editor vi).

    • If configuration values are wrong and you don't know which action can fix it, the simplest way is to edit the configuration file (mostly git config --global --edit). Git opens the associated configuration file with the preferred editor and the user can change anything he wants. As an example, I erased configuration variables that made not sense (typos).

    Tab. Edit the configuration variables

    Command Description
    core.editor

    By default, Git uses the text editor specified by one of the shell environment variables VISUAL or EDITOR, or else falls back to the vi editor to create and edit commits or tag messages. On my system none of the variables above are populated. I set core.editor=gvim as a global option (user default).

    commit.template

    The value of this option is the name of a text file that git will read to initialize commit messages. The use of a template reinforces rules regarding formatting and style, especially within an heterogeneous team.

    I defined the (hidden) text file ~/.gitmessage.txt in my home directory as a default message template for all my projects (i.e. git config --global commit.template=~/.gitmessage.txt).
    core.excludesfile

    To ignore file patterns for all repositories a user may write them into a file stated in option core.excludesfile. I added following option git config --global core.excludesfile ~./.gitignore_global.

    # -----------------------------------------------
    # LABEL: Git ignore files option # INFO: lists templates of files that do not belong to any git project
    # -----------------------------------------------
    # NAME: /home/akh/.gitignore_global

    # ignore macos system files
    .DS_Store

    # ignore temporary files
    .*.swp
    TODO
    # ignore Document files that are not part of the development
    # .*.[Pp][Dd][Ff]
    # .*.[Pp][Nn][Gg]

    # END_OF_FILE
    Tab. Content of file gitignore_global

    For details about the syntax (regular expression) look at Git doc: gitignore.
    Other interesting variables

    Herewith more configuration values I stumbled upon in the course of time. Without explanation.

    • git config {--global} init.default branch main

    Tab. Some handy configuration options, see also Git doc: configuration options.

  5. Git Processing - Basics

    Warnings:

    • Syntax: Between Git and other VCS, actions bearing the same name might not perform same tasks. (Mostly, due to the versioning model : A VCS may act as a local, a central or - like Git - a distributed data base.)

    • Sources: Tables below shall be merely regarded as 'field notices', exhibiting only most characteristic features that occurred to me when reading the documentation and practising. Exhaustive documentation about all Git commands, classified according to their tasks, is published on the official site, at git-reference-page.

    1. Set a Git Project

      Start a Git (controlled) project means add a (local) repository. There are 2 ways to achieve this goal:

      1. Create an Git repository to maintain an existing project (that has not yet be placed under control) - and make it available to other developers.
      2. Clone an existing Git repository - as a rule, created by third developers and possibly stored remotely.

      1. Create a Git repository

        No. Command Description
        1

        cd /path/to/project/dir

        Change to the directory where the files to maintain are located.

        2

        git init

        This creates a new subdirectory into the project directory, named .git that contains all necessary repository files.
        Note:

        • A this point nothing has been tracked yet!

        3

        git add *.html
        git add *.css

        git add *.png
        git add *.jpg
        git add *.gif
        git add *.ico

        git add *.odg
        git add *.odp

        git add *.txt
        git add *.zip

        Obviously add [file] means 'include files (pattern/s) to tracking list. More precisely add [file] means 'add content to next commit'.
        Note:

        • Git implicitly refuses to track specific file name patterns, like *.pdf.
        • Users can define additional patterns to ignore.

        4

        git commit {-m <comment>}

        Example: git commit -m 'initial version of www.khelil.de [0]'
        Note:

        • Added files (marked as staged) are not secured until they have been committed.
        • Each commit must be associated to a comment.

        Tab. Start tracking an existing project into Git (example of Project khelil.de)

        Note: A repository may maintain several development branches. In most cases, command argument master will, by default, designate the main development branch in the local repository.

      2. Clone an existing Git repository

        No. Command Description
        1

        cd /path/to/root/dir

        Change to the (root) directory where the git project (the files to maintain) will be located (as a sub-directory).

        2

        Copy from a local repository:
        git clone [/path/to/repository]

        Copy from a remote server:
        git clone {username@host:}[url_of_source] {target_dir}

        Cloning a repository is more than just checking out a project - as may be the case with other VCS.

        Git does not only transfer a screenshot of project data - as might be the case for some source control programs -, but includes maintenance information (almost) one to one - especially, the history of all tracked data is pulled down, by default.

        Several transfer protocols are commonly used:

        • HTTPS: e.g. git clone https://github.com/libgit2/libgit2 mylibgit
        • SSH: e.g.git clone user@server:path/to/repo.git

        Tab. Cloning an existing repository

        Note: In most cases, command argument origin will, by default, designate the main development branch in remote repository.

    2. Maintain a Project

      Diverse actions are available depending on how developers are currently interacting with the project development process.
      The table below (also inspired by Roger Dudler) shows main use cases.

      No. Command Description
      1

      git add <file name(s)>
      extend the list of "staged" files.

      Mark file into the staging tree (set of the next commit candidates)

      Files in the working directory, modified or new - since the last commit on the working branch -, are tagged for the next commit i.e. staged.

      Note:

      • Only "staged" files can be considered when a commit is launched.
      • If a file has been staged and then modified anew, before any commit has been performed, Git will differentiate between the (last) modified and the staged version.
      • If pathname is a (naked) directory, all files in directory are accounted for recursively.
      • git add *: all changed files within control are transferred into the "staged" status.

      1b

      git restore --staged <file name(s)>

      It reverses command git add - i.e. "un-stage staged files": After processing <file name(s)> is/are no longer listed as staged files (does/do not belong to the next commit anymore) - see also f.e. TOWER: git restore

      2

      git commit -m <commit_message>

      commit the (staged) files into the current branch

      Each time the project reaches a state worthy of recording, its snapshot should be committed. Changes that have not been committed are eventually lost.

      For references see following pages:

      Note:

      • Staged files are committed to HEAD.
      • Each commit must be associated to a comment.
      • Changes must be pushed in order to affect a remote repository: Even if the local repository is connected to a remote one, nothing has yet been done to update the latter.
      • Change a commit message:
        Sometimes, the developer (or another responsible actor in the project) wants to change the commit message text (for example because some piece of information is incorrect or confidential).

        If the reaction takes place immediately after the commit has been made (before it has been published/pushed), option --amend is appropriate, i.e. git commit --amend -m "<CORRECTED_MESSAGE>"

        For more references, see following pages:

      3

      git branch <name_of_branch>

      Create a new development branch

      For example git branch testing to create branch testing as in Fig. 5.

      Note:

      • Command branch does not switch to the newly created branch automatically (In other words, HEAD. remains unchanged).

      4

      git {-b} checkout <name_of_branch>

      Switch to branch name_of_branch

      For example git checkout testing moves HEAD to branch-object testing - see Fig. 6.

      Normally a user switches to (checkout) an existing branch.
      However, by means of option -b Git allows to perform both steps, creation and switch, at once: git checkout -b <name_of_branch>.

      5

      git tag

      tags a given commit

      A tag (object) is a convenient way to identify a commit, if the associated hash is perceived as too cryptic.

      For references see following pages:

      Some examples of usage:

      • git tag -l <pattern>... or git tag --list <pattern>... lists all tags (if running without further arguments) or only those tags matching the given patterns.
      • git tag -l -n<number>... lists all tags. number specifies how many lines from the annotation, if any, are printed. Option -n without number will show the first line of the annotation.
      • To get detailed information about a specific tag type command git show [<TAG_ID>] e.g. git show v2.0.0
      • git tag -a v3.0.0 -m "[khelil.de] [January 2023] reshaping the formatting and add minor corrections "

      Tab. List of Git actions for project maintenance

      Note:

      1. The user can define a list of files to ignore i.e. that must not be tracked. They must be registered into the ignore list - stored in the .gitignore file of the repository directory. Each line corresponds to a file name pattern. Following rules apply:

        • Blank lines or line starting with # are ignored.
        • Standard glob patterns work.
        • Start patterns with a forward slash (/) to avoid recursivity.
        • End patterns with a forward slash (/) to specify a directory.
        • Negate a pattern by starting it with a exclamation point (!).

        See also examples in gitHub.

      2. Each commit must be associated to a comment (clearly identifying the update).
        Mostly, the comment will be inserted in-line (option -m <comment>).
        However, if option -m is missing, Git will display a text - invoking the preferred editor. This text includes commented lines (output of git status), supposed to help the user enter an appropriate commit-comment - as uncommented lines.(Note: If commit option -v (verbose?) is activated, the amount of information displayed increases to the output of git diff.)

      3. Removing files
      4. Moving (renaming) files

    3. Remote synchronization

      No. Command Description
      01

      git push [remote-name] [(local) branch-name]

      Update remote repository

      Only committed changes are part of the transfer between local and remote development branch. By default,

      • [(local) branch-name] (here the source branch) is master.
      • [remote-name] (here the target branch) is origin.

      02

      git remote add [remote-name] <server>

      connect local repository to a remote server

      This operation can be considered as opposite to project cloning. After this, it shall be possible to push locally committed changes to the selected remote server.

      Note:
      In many cases, [remote-name] (the name of the remote repository connected) shall be origin.

      Tab. List of Git actions: Remote interactions

    4. Get pieces of Information about a Git Repository

      After working on a repository for a while, files may be (still) untracked, changed, staged, committed. There are several commands available to obtain more information about the current status of files.

      1. Command git-status
        git status {options} {--} <path>
        lists paths (files) with following characteristics:

        • paths where states of index and current HEAD differ
        • paths where states of working tree and index differ
        • paths in the working directory that are not tracked

        See also manpage git-status.

        Note:
        If files have been added to the working directory, they are automatically marked as untracked. If registered files have been modified, they are marked as modified. Both untracked or modified files must be staged (Git command add), before they can be part of the next commit.

        No. Command Description
        1

        git status

        For example, if the command is run directly after cloning, Git issues following message:
        On branch master
        Your branch is up-to-date with 'origin/master'
        nothing to commit, working directory clean

        There is no untracked, modified, nor staged file - otherwise git would mention it.

        Note:
        Git mentions the associated development branch: By default, the local development branch is named master and the remove development branch is named origin. They can be renamed, if need be.

        2

        git status -s
        git status --short

        This short version of 'get status' displays information in a more compact way.
        One line for each file. Column 1 shows the status of the staging area, Column 2 the status of the working area. One of the following attributes may appear in each column:

        • Files that aren't tracked have a ??
        • Files that have been added have an A
        • Files that have been modified have an M

        Tab. Checking status using git status

      2. Commands git-diff

        git diff {options} <commit> {-- {<path>}}
        git diff {options} --cached <commit> {-- {<path>}}
        git diff {options} <commit> <commit> {-- {<path>}}
        git diff {options} <blob> <blob> {-- {<path>}}
        git diff {options} --no-index {-- {<path>}}

        allow a detailed view about file changes (lines added and removed in each file).

        Depending on options and parameters different states may be compared:

        • states within current branching
        • states of commits belonging to different branches.

        See also manpage git-diff.

        No. Command Description
        1

        git diff {--options} <commit>

        Compares the working directory to the named commit.

        If <commit> is not named, the default value HEAD applies and git-diff shows changes that would be committed, if command git commit -a is run.

        2

        git diff {--options} --cached <commit>

        Compares changes between the index and the named commit.

        If (default) commit value HEAD applies, git-diff shows changes that would be committed if command git commit (without -a) is run.

        3

        git diff {--options} <commit> <commit>

        Compares changes between 2 arbitrary commits for all entries identified (which may amount to a tremendous set of data).

        By inserting additional options -- <path> the user may focus on specific files

        4

        git diff {--options} <commit>..<commit>

        As the previous command, it compares changes between 2 arbitrary commits.

        However, if one of both commits is not named, the default commit value HEAD applies.

        Tab. Checking status using git diff

      3. Command git-log
        git log {options} {<revision_range>} { {--} <path> ...} shows a list of commit logs along the current development branch.

        See also following references:

        There are options for control the output flow: which data are displayed, which commits shall be accounted for, which files are of interest. Mostly are independent from each other. Some popular option combinations are shown in the table below.

        The command displays all current commits registered with the repository. If they have been marked as a 'branch' - i.e. pointed at by a branch-pointer -, the information is also displayed.

        No. Command Description
        1

        git log

        By default (i.e. without option) , git-log displays following 4-tuple (commit name, author, date, comment) in anti-chronological order for all commits in the current branch.

        2

        git log -p -<revision range> -- <path>

        Option -p (meaning 'generating patches'):
        Shows the differences introduced in each commit by means of diff (i.e. displays all modified lines for each entry).

        For example:
        git log -p -1 -- Quellcode/PST/Bildbearbeitung/*.cpp will display diff for entries meeting following conditions:

        • Only the last commit is considered (option -1).
        • Only cpp-files in directory Quellcode/PST/Bildbearbeitung are considered.

        3

        git log --stat -<revision range>

        Option --stat:
        Shows the differences introduced in each commit by means of diff-stat (i.e. displays a summary of modifications for each entry).

        For example:
        git log --stat -1 All entries involved in the last commit are accounted for. For each of them a summary of changes is displayed.

        4

        git log --pretty=oneline

        Option --pretty:
        The pretty format has several pre-defined values like oneline, short, medium, full...

        5

        git log --oneline --decorate

        6

        git log --pretty=format:"{<tag>...}"

        The user may even determine a specific format of its own using placeholders (tags) like in the following example: git log --pretty=format:"%h, %ad, %Cred%an%Creset, %s --date=short" will display in one line following data: abbreviated commit hash, author date, author name, subject.

        • The predefined format git log --pretty=oneline is equivalent to --pretty=format:"%H %s"
        • In the example above, the author's name will be written red (thanks to syntax %Cred ... %Creset).
        • Long commit hash would have been %H instead of %h.
        • The user defined format above can be stored into config file (~/.gitconfig), using following lines of code:

          [log]
          date = short
          [format]
          pretty = format:"%h, %ad, %Cred%an%Creset, %s"

          Instead of tipping the whole format sequence, the use now just needs to tip git log to shape the output as he defined.

          For more details (f.e. creating aliases) see also stackoverflow: the shortest possible output from git log containing author and date

        Tab. Checking status using git log

        Remarks:

        • If the output does not fit into a single window, the default pager (e.g. LESS ) is invoked.
        • In option <path> the use of glob patterns is allowed.

  6. Git processing - More

    I only covered the very basics in the chapter above. This are many more possibilities of treatment that I do not know of to a great part. In this chapter I will treat some of those extensions, if I come across them and if I have the time to report.

  7. Examples of Git projects
    The term 'project' in this context refers to a single repository or a group of them associated with the same content. Obviously, I will only mention projects in which I have been involved.

    1. Project khelil_de

      khelil.de comprises a set of HTML files describing issues that I studied and documented in the course of years. It has been maintained on a local Git repository that, for the sake of clarity, I will call khelil_de_0.

      There are different ways to "export" the local repo to remote ones: a remote (central) repository (theoretically) enables associated persons to work on the same project. In the next chapters (khelil_de 1, khelil_de 2), I will explore some of those possibilities using precisely project khelil.de, that is currently (2023-10) a major project of mine. However, this is not only about khelil.de. The final goal is to maintain (future) projects, designed from the scratch to be distributed: I intend to document how this done in dedicated chapters.

      1. Local projekt khelil_de_0:
        Status from March 2023 on

        I used following git commands to set up the project.

        git status {--short}

        Display the list of files bearing following characteristics.
        (1) The ones that have changed but are not yet marked as part of the next commit
        (2) The ones that have changed and are marked as part of the next commit. (In git jargon those files are labeled "staged").

        Note: Staged files that changed subsequently are listed in both sets (with a different content).
        git add --all

        All changed files are marked as "staged" i.e. ready for commit

        git commit --file="txt_0" Commit with a message stored in git_commit0.txt - with for example following content:

        Clean Cut state for [www.khelil.de] (Vorabversion 1)

        For ALL pages
        - clean CSS Page (remove unused formats)
        - relax HTML formatting (u.a. no 'px') and purge unused class token
        - copyright label

        For single pages
        - Introduce a "Contents page" exclusively displaying pages written in English and linking where appropriate
        - Improve git documentation

        KEYWORDS: Formatting, Copyright, contents display, git

        git commit --amend -F="txt_1"

        If need be, update the message of the last commit, replacing it with the content of git_commit1.txt. (Options --file or -F are the same)

        git tag -a v3.0.0

        Now that a clean cut state has been committed into the repository, it will be associated to (tagged) version 3.0.0. This is a annotated tag.

        Example: List of git commands necessary to archive a state denoted "Clean Cut 2023-02-06" into the repository

      2. remote repo khelil_de_1
        Status from October 2023 on

        Remote repo, labeled khelil_de_1, associated with local repo, labeled khelil_de_0, will be stored into the very same web space, where khelil.de is hosted. It will be created as a bare remote clone of khelil_de_0 and may later serve as a central archive.

        By convention, bare git repositories bear the .git extension: the "real" name of the remote project may well be remote_khelil_de_1.git.

        remote_khelil_de_1.git theoretically enables a distributed development: Each developer pushing and pulling their work to or from the central repo.
        Whether this concept is practical or not, critically depends on one external factor: access rights into my webspace: git needs ssh access to the remote host. The contract with my provider currently allows only one single ssh-user onto the web space, me. No way to create another user named f.e. git, in whose profile the repository would be stored and to which all team members would have access (configuration recommended by the git developers cf. git docs: getting git on a server.

        This restriction may somewhat be overcome, by adding (RSA) public keys into file ~/.ssh/authorized_keys of my single user account. As a matter of fact, I already authenticate myself into the webspace using a RSA key (rsa-akh-ionos). Whether git using this key will be able to access remote_khelil_de_1.git properly will be documented in the next chapters.

        Note however the major disadvantage of the work-around presented above: all team members would have complete access onto my webspace - and not only the repo directory. I cannot afford such a security leak. Still, if the bare repo remote_khelil_de_1.git is successfully configured, I can use it as a valuable personal archive (a backup).

        My references (helping me set up and configure remote_khelil_de_1.git)

        Steps and explanations

        Conditions /assumptions

        • ssh access to remote (directory) host - where repository remote_khelil_de_1.git will be stored - using RSA key sshRSA_khelil_de for authorisation.
        • Local khelil_de_0 project is maintained in local repo local_khelil_de_0.git

        Commands

        1

        git clone --bare --verbose
        <local_khelil_de_0> <LocalCloned_khelil_de_0.git>

        Go to the directory where the initial local git repository stays and clone it locally into a dedicated directory.

        Note:
        You may want to clean up the repo (git gc) and check its integrity (git fsck --verbose --full --strict) before cloning it.

        2


        (1) scp -r -v <LocalCloned_khelil_de_0> <MyUser@MyWebSpace:/path/to/> or

        (2) scp -r -v <LocalCloned_khelil_de_0> <MyHostname:/path/to/>

        Transferring the locally cloned bare repository onto the server (remote host) using command scp. The set options are "recursive" (for a directory) and verbose (to verify whether the copy process works fine).

        In alternative (2), variable <MyHostname> is an alias for MyUser@MyWebSpace including some more communication parameters, if the ssh communication has been configured properly - see also ssh configuration.

        Note that <LocalCloned_khelil_de_0> (the locally cloned repo) and <Remote_khelil_de_1.git> (the remote repo) have the same literal name in this case.

        3
        1. ssh <user>@<webspace>
        2. cd </path/to/myClonedRepo.git>
        3. git init --bare --shared
        Open a shell on the remote host and go to the directory of the remote git repo and perform proper initialization (all user having a ssh account will be able to push and pull). It is also recommended to check the integrity of the remote repo.
        4

        git add remote remote_khelil_de_1 ssh://<myHostName>:<remote_khelil_de_1.git>

        Go back to the local git project khelil_de_0 and add the remote project khelil_de_1 to the list of the associated remote project, to allow push and pull using alias remote_khelil_de_1.

        5

        git push remote_khelil_de_1

        This is the moment of truth: First time we try to push the next local commit into the remote repo.
        Success: The feasibility of this path has been demonstrated.

        After both repositories (local, remote) have been synchronised for the first time, the future synchronisation steps will invariably follow the same pattern.

        0

        git branch --all
        git remote -v

        Preliminary check of local and remote branches

        1

        git pull <remote_khelil_de_1> <remote branch>

        re-sync (fetch and merge) current branch of the local repo using remote branch as the source. In this project, all new developments take place on the local repo: git pull is not supposed to disrupt anything.

        2

        git push remote_khelil_de_1

        After the pull step is completed, git authorizes the push step from local to remote.

        Next step (next chapter) will be to assess remote host GitHub that is explicitly designed to enable distributed development.

      3. Repo remote_khelil_de_2
        clone Khelil_de_0 to the gitHub webspace?
        Status from October 2023 on

        I have a (free) account on gitHub, currently with one visible empty public repository: test0. The obvious questions are:
        How to export khelil_de_0 to gitHub khelil_de_2 under which conditions, limitations or dangers?

        GitHub conditions and limitations
        ref. also gitHub: Access to repos

        Having a free account, labeled AmarKhelil, I can https-login to my personal webspace at https://github.com (with Username, password).

        My profile is labeled personal and public.
        In fact, it is an essential part of the gitHub process that actors and results are "public". The paradigm is that developers place their work (i.e. the files in their repositories) under public scrutiny, so that, in return, they may get help, guidance, corrections from (at first) unknown experts who may eventually become collaborators, developing additional branches (features) into the project. As a matter of fact, the primary contents under control are
        (software) codes.

        Note: A personal "private" profile would make little sense - unless being some kind of ghost silently spying on repositories. Companies may create "group" accounts (and associated repositories) accessed by co-workers who are internally individually identified. Another story.

        Can any repository be labeled "private" - meaning invisible to the general gitHub folk?
        Yes, but they offer - in the free subscription - limited interactions, compared to "public" repos: number of collaborators, branches, etc. ? It is in therefore generally preferable for repositories to be entirely visible for all gitHub users. Everybody will be able to fork the codes for their own purposes. Off course, they will not be able to directly modify the content of the original repo itself, even if public. One must have been explicitly invited to collaborate to get the read/write permission. (Note that a collaborator in a personal account always get both permissions at once).

        khelil_de is a one man project. No fancy code management here. I will declare khelil_de_2 private.
        (Note: it is always possible to declare the repo public, if need be afterwards. Transfer private-to-public is much easier than transfer public-to-private).

        Generate and check ssh key
        I have created a ssh key (labeled rsa-akh-github) to authenticate myself onto my gitHub account - for details see also ssh key generation. I then uploaded it directly onto my gitHub account, via the https Interface: copy and paste of the public key value into the window provided by the GitHub menu "Settings/Ssh-keys/New"
        Note: It is not recommendable to upload ssh key from other folks onto one's gitHub account, because this would give them unlimited access to all repositories - see also next chapter (ssh key use). (Since gitHub - at least in the standard configuration - does not support opening a ssh-shell, one may hope that only repos are compromised in this case, not the whole account.)

        After rsa-akh-github has been generated and (its public component) uploaded onto my gitHub account AmarKhelil, the ssh communication between local and remote git repos must be configured in the local profile ~/.ssh/config - see also ssh key configuration. Here are the config parameters related to my gitHub:

        ### ssh login für gitHub
        Host github
        Hostname github.com
        User git
        PreferredAuthentications publickey
        IdentityFile rsa-akh-github

        Retracing the steps...

        1. Open a bash shell and load the proper rsa key into memory (see e.g. ssh key add). To check whether the task was successfully completed, one can type ssh-add -l (display parameters of publich key) or ssh-add -L (display public key value).
        2. Type ssh -T github (The -T option means "disable pseudo-terminal allocation")
          It was a success. GitHub returns following message: Hi AmarKhelil! You've successfully authenticated, but GitHub does not provide shell access. As already mentioned, to minimize security leaks, GitHub does not support by default shell access. (But, there may be a way... see below)

        Transfer from local (khelil_de_0) to remote (khelil_de_2)

        1

        git remote add remote_khelil_de_2 git@github.com:AmarKhelil/remote_khelil_de_2.git

        Go to the directory where the initial local git repository (khelil_de_0) stays and add the remote repo remote_khelil_de_2.

        2

        • git branch -M main
        • git branch --list -a

        The main development branch used to be called master. And it was at least the case for my local repo khelil_de_0. After the first command has been performed, the master branch is renamed main - which can be verified by typing the second command.

        3

        git push {-u} remote_khelil_de_2 main

        Transfer the main branch (of local) to remote.
        I put option -u (= set-upstream-to) as optional. In this case it would set remote_khelil_de_2 as the remote repo - when commands git push or git pull do not specify a remote.

        The transfer was eventually successful:
        remote_khelil_de_2 has been created and populated on gitHub. Branches khelil_de_0/main (local) and remote_khelil_de_2/main are synchronized.

      4. A shell for GitHub

        References

        gitHub: installation The git CLI project (gh repository) as well as links describing the installation procedure in widespread operating systems.
        gitHub: installation Installing gh on Linux and BSD: the exact commands to run. []
        gitHub: Quick start CLI
        An overview about the most important commands and options for gh
        gitHub: CLI Manual
        Reference documentation about the gh syntax and options

        To open a shell on the own git repositories on must first install a program named gh. To check the successful installation, type gh --version. Now (2023-11-01) the command responds following on my (bash) termin

        gh version 2.38.0 (2023-11-01)
        https://github.com/cli/cli/releases/tag/v2.38.0

    2. New Mobility Concepts in LU

      1. Motivation

        As a newcomer in the city of Ludwigshafen (LU, Palatinate, Germany), I eventually came to learn about a highway reconstruction project in the city center that a majority of local politicians has been supporting since its initial planning in 2015. In September 2023 they launched its realization after the federal and local states (Bund and Bundesland) agreed in substantially financing the project: 85% of the total cost, estimated in year 2021 to be ca. 600 millions Euro, assuming no inflation during the construction period.
        Since the first drawings, engineers and local deciders were unequivocally dedicated to promoting inhibited car mobility through the city center. Their projections onto the year 2040 assume an increased traffic density of 30% up to 50% compared to 2022. The system, 2 highway axes - north and south of the city center -, absorbed about 100 000 cars a day in August 2019, at the time when the south axis was closed because of damages. (The city itself counts about 170 000 inhabitants).

        The local politicians in LU have already a rich history of failed mega-projects.
        The last scandal is located in the city central place named "Berliner-Platz", that has been a building site since 2015 (for 8 years now). In July 2022 the investor went bankrupt. To this date (November 2023) the communal authorities have no idea on how to tackle the situation.

        Citizens organized protest actions against the failed 'Berliner-Platz Project' and hosted a home page at Bilelu (Bürgerinitiative Lebenswertes Ludwigshafen). At some point, they decided to extend their protest to include the project "LU Central Highway aka Helmut-Kohl-Allee": The more one thinks about it, the more it becomes obvious that this mega-project have huge drawbacks that designers underestimated in 2015 - if they were even aware of them at all. Those omissions may well lead the city into a financial, social and ecological collapse. Still, most local politicians keep repeating that "there are no alternative solutions" (to the mobility question). Is it true? To get elements of response, I will open a web site exploring innovative mobility concepts in LU and comparing them with respect to various criteria.

        Contents will be created locally and secured remotely - to allow several people to work in parallel, if they decide to join in.

      2. Local repo mwlu_de_0

        As is the case in project khelil.de, I will maintain 3 git repositories.

        1. A local git repository, called mwlu_de_0, on my computer - in a directory called /path/to/mwlu_de.
        2. A remote git repository in the manitu webspace, where the HTML pages are actually hosted - called mwlu_de_1.
        3. A remote git repository on my github account, called mwlu_de_2.

        Note that, as the task started, there was only one git repo existing, mwlu_de_2 (on github).

      3. remote repo mwlu_de_1

        In the manitu webspace, HTML pages mobilitateswende-lu.de are stored in a directory called /web/mobilitaetswende-lu.de.

        UNSUCCESSFUL ATTEMPTS:

        At first, I tried different approaches involving a "bare" git repository, stored in a dedicated directory /path/to/web/mwlu_de.git. It did not work: I was unable to connect the local git mwlu_de_0 and remote (-bare) /path/to/web/mwlu_de.git.

        Command git remote add remote_mwlu_de_1 ssh://<host_manitu>:/path/to/web/mwlu_de_1 throws an error.

        /path/to/web/mwlu.git was a copy of a local bare git repository, cloned from local git repository mwlu_de_0, and subsequently sent onto webspace - via command scp.

        The connection with remote /path/to/web/mwlu_de.git constantly broke with the same error telling that /path/to/web/mwlu_de.git was not a repository or that access permissions were insufficient. Both allegations proved wrong, after opening a ssh connection and directly verifying. The true cause of the problem remains however obscure.

        SUCCESSFUL PATH:

        The list of commands that lead to success:

        1. [] Create a working git repository within the webspace directory /path/to/web/mobilitaetswende-lu.de where the very HTML pages are maintained. [] Introduce the first commit "initial content of the webpage". [] Verify: git status, git log.

        2. Go into the directory where the local repo mwlu_de_0 must be: /local/path/to/mwlu_de.

        3. git clone ssh://<host-name>/path/to/mobilitaetswende-lu.de: Clone the remote repo into the local directory: A local git copy of the remote git repository is created.

          Note: In the ~/.ssh/config file, there must be a Host <host-name> entry with all the correct ssh connection parameters: Hostname, Port, User, IdentityFile - see also ssh configuration.

        4. git add remote remote_mwlu_de_1 ssh://<host-name>/remote/path/to/web/mobilitaetswende-lu.de

          This time, the connection local to remote is successful: It can be verified e.g. by issuing command git remote -vv.

          Note: I had to issue command git remote rename origin remote_mwlu_de_1, to finally get the remote link-name remote_mwlu_de_1, instead of origin (the default link name). (I don't know what went wrong in the first place. Maybe, I actually forgot to explicitly state the link name).

        5. git pull remote_mwlu_de_1 main. If successful, the git pull and push operations between local and remote are available. Job done.

      4. remote repo mwlu_de_2

        FIRST ATTEMPT:

        I created mwlu_de_2 in my github space before doing anything locally. The first (and only) file incorporated was readme.md describing the general scope of the project - which is some kind of mandatory step when starting a repo on github. (The github readme.md file can be formatted using a simplified syntax as explained in formatting readme.md files in github.)

        1. Step: Open a ssh-communination channel with github.

          Assuming that the ssh authentication key (public key) has been stored into the list of accepted keys onto the github account, and that the corresponding (secret) key has been upload into the working memory ( using command ssh-add), and that the ssh-config-file writes correct parameter values (see configure the ssh communication), just type command ssh -T <host> to verify that the connection works. (Even after a successful connection, github does not permit opening a remote shell).

        2. Step: Clone the github repo - see also clone a github repo
          Using command git clone <name_remote_github_repo.git>. The correct name is easy to find. Login onto your account in github and select the repository in question. Open menu "<> code" and select the communication protocol (https or ssh).

          ssh address of mwlu_de_02 in github
          ssh address of mwlu_de_2 in github

          Using command git remote -vv, the connection to the remote github repo becomes visible. By default, the remote repo is named origin. Since I will be working with several remote repos connected to the same local working repo, origin will be renamed to remote_mwlu_de_2 using command git remote rename origin remote_mwlu_de_2.

          remote github repo mwlu_de_02
          remote github repo mwlu_de_2

          Note here that due to having first uploaded the wrong ssh-key for github, I transitorily ended up using the https connection to the remote github repo. This situation can however be fixed using command git remote set-url remote_mwlu_de_2 git@github.com:AmarKhelil/mwlu_de_02, forcing the ssh connection instead of the https connection.

          remote github repo mwlu_de_02
          remote github repo mwlu_de_2

        3. Step: pull remote

          git pull remote_mwlu_de_2 main

          SECOND ATTEMPT:

          After I finally succeeded in connect local mwlu_de_0 to remote mwlu_de_1, I have to reconnect mwlu_de_0 with mwlu_de_2 on github. Note that in the meantime, I renamed the remote github repository mwlu_de_2 (instead of MWLU_de_02), for consistency reason.

          1. First re-step is git remote add remote_mwlu_de_2 git@github.com:AmarKhelil/mwlu_de_02

          2. Next step is git pull remote_mwlu_de_2 main.
            Well that is where the real work begins, because in the meanwhile remote_mwlu_de_1 main and remote_mwlu_de_2 main have diverged. What must be done? a git-merge or a git-rebase? - cf. also atlassian: merging vs. rebasing.

    3. Automatic Generation of HTML Pages

      1. Original Motivation

        So far, HTML-files in www.khelil.de have been written manually and maintained in a single repository.
        In the future, HTML files will, under circumstances, be generated automatically. The idea is based on a proposal by Patric Sokoll (PaSo). In PaSo's virtuelles Röhrenmuseum thousands of pages have been published, each one dedicated to a single item in one museum: electronic tubes, medical devices, computers, etc. Most of the pages are cross-referenced. Manual maintenance is therefore prone to failure. On the other hand, automatic page generation is made easier because of following reasons:

        • The data treatment scheme is the same for all items,
        • The data is stored in a Data Base (PostgreSQL).

        Patric Sokoll wrote (at least) 2 C++ Libraries on the top of the Qt library. Each maintained in a separate Git repository.

        No. Name of Git repository Short Description
        1 PST-MuseumsWelt Automatic generation of HTML pages by extracting data stored in a DB into a HTML blueprint. It relies on library PST-Tools
        2 PST-Tools It codes the most basic treatment level.
        Tab. Repositories created by Patric Sokoll to generate his museum pages

      2. Status 2018
        In a first feasibility project, I intend to publish pictures and paintings - see also Virtual Exhibition. Those works will be referred to in a data base (e.g. PostgreSQL) along with their characteristics. Tasks and conditions are similar to those identified by Patric Sokoll for his virtual museums. We agreed on a cooperation: I will clone the PST repositories above. If need be, codes will be adapted / extended into separate Git branches.

      3. Status 2023
        No progress since the declaration of intention, years ago and unfinished HTML-templates: Only a few new pics or images have been published in the meantime. It is unclear whether the project will ever be realized. Probably yes, if a project Photo Exhibition comes into life. However, tools and ways may differ completely from the original design.

  8. Further Git References

    No. Link/Name Short Description Language
    1 Lexicon/Git

    Git Entry in Lexicon with links to pages containing a general information about download, documentation and tutorials.

    German, English
    2 git help <action>
    git <action> --help
    man git-<action>.

    Get help for a specific action.
    You may for example type git help config to get information about the configuration command.

    English
    3 Manpage git-config

    Manpage of Git Config in www.kernel.org (Linux Kernel Archives).

    English
    4 Pro Git Book

    Written by Scott Chacon and Ben Straub and available to read online for free.

    English
    5 Git Reference Manual

    Git Reference Manual.

    English
    6 Git: the simple guide

    The Git essentials without (I cite) "deep shit". Very worthy.

    Many languages.
    7 Git Tutorial w3school

    Git Tutorial

    English
    Tab. "Links about Git"

    Rem.: Another possibility to retrieve specific informations is to type Git help or Git Action help.