Developer Blog

Tipps und Tricks für Entwickler und IT-Interessierte

Jupyter | Cookbook

Cookbook

Customize start dir

$ jupyter notebook --generate-config<br>
Writing default config to: /Users/demo/.jupyter/jupyter_notebook_config.py

Search for the following line in the file

#c.NotebookApp.notebook_dir = ''

Replace by

c.NotebookApp.notebook_dir = '†/the/path/to/home/folder/'

Change password

jupyter lab password

Free online Notebooks

https://notebooks.azure.com/

https://nbviewer.jupyter.org/

https://colab.research.google.com/notebooks/welcome.ipynb

github

Git | Using multiple accounts with Github

Create a New SSH Key

We need to generate a unique SSH key for our second GitHub account.

$ ssh-keygen -t rsa -C <your email address>

Be careful: do not over-write your existing key for your personal account. Instead, when prompted, save the file as id_rsa_<account name>.

I saved the file to ~/.ssh/id_rsa_placeholder

Attach the new Key to your Github Account

Next, login to your second GitHub account, browse to “Account Overview,” and attach the new key, within the “SSH Public Keys” section.

Copy and paste the content of the generated ssh file (with extention .pub):

~/.ssh/id_rsa_placeholder.pub

Note: Be sure to give this key a descriptive title, so that you can remember the source of the key.

Configure you shell environment

Start the ssh-agent, so that we can remember ssh-keys.

$ eval $(ssh-agent)
Agent pid 5099

Note: If you want to automatically start the agent on login, please look at the profile script at the end of this article

Now, add the key to the ssh-agent

$ ssh-add $HOME/.ssh/id_rsa_placeholder
Identity added: /home/ralphg/.ssh/id_rsa_placeholder (/home/placeholder/.ssh/id_rsa_placeholder)

Verify, that the key is loaded

$ ssh-add -l
2048 SHA256:ZOvzhxxxMVxxxOsMxxxm2YxxxHpV4/eAiFWyKJVRl/xxxxx /home/placeholder/.ssh/id_rsa_placeholder (RSA)

Now, configure your github repository

$ git remote -v 
origin https://github.com/placeholder/Awesome-Github.git (fetch)
origin https://github.com/placeholder/Awesome-Github.git (push)

Configure repository to use this ssh-key

$ git remote remove origin
$ git remote add origin git@github.com:placeholder/Awesome-Github.git
$ git remote -v
origin  git@github.com:placeholder/Awesome-Github.git (fetch)
origin  git@github.com:placeholder/Awesome-Github.git (push)
$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
$ git push --set-upstream origin master
The authenticity of host 'github.com (140.82.118.4)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,140.82.118.4' (RSA) to the list of known hosts.
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 5.55 KiB | 567.00 KiB/s, done.
Total 5 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:placeholder/Awesome-Github.git<
    1679693..3bbeede  master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.<

Configure your repository to use the created ssh-key

$ git config core.sshCommand "ssh -i ~/.ssh/id_rsa_placeholder"

Appendix

Shell profile script for autostart ssh-agent

SSH_ENV="$HOME/.ssh/environment"

function start_agent {
    echo "Initialising new SSH agent..."
    /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
    echo succeeded
    chmod 600 "${SSH_ENV}"
    . "${SSH_ENV}" > /dev/null
    /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
    . "${SSH_ENV}" > /dev/null
    #ps ${SSH_AGENT_PID} doesn't work under cywgin
    ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
        start_agent;
    }
else
    start_agent;
fi

Script: create_ssh_keys

#!/bin/bash

GITHUB_ACCOUNT="$1"
echo ssh-keygen -t rsa -C "${GITHUB_ACCOUNT}@via-internet.de" -f id_rsa_${GITHUB_ACCOUNT}

Script: update_ssh_keys_to_HOME

#!/bin/bash
FLDR_DST=$HOME/.ssh

for _FILE in id*
do
    echo "copy $_FILE"
    FILE_DST="${FLDR_DST}/$(basename $_FILE)"

    chmod 600       $FILE_DST
    cp  $_FILE      $FLDR_DST
    chmod 400       $FILE_DST
done

Jenkins | Getting started

Introduction

What is Jenkins. From the Jenkins Homepage, you will get this:

The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project.

As an extensible automation server, Jenkins can be used as a simple CI server or turned into the continuous delivery hub for any project.

This blog will describe, how to setup jenkins and build an environment where we can build and test a simple python app: a calculator.

Setup Jenkins

Jenkins is a java application. So, to run jenkins, we need to things:

  • a java development kit
  • a jenkins war file

Following the requiements rom the jenkins home page, we should use java8 to run jenkins.

To check your java version, open a console an run

java -version
openjdk version "1.8.0_242"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_242-b08)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.242-b08, mixed mode)

If you need to install the right java version, get it from here.

Download WAR

Next, we need Jenkins. Download the Jenkins here. We will use the weekly generic java package (.war)

wget http://mirrors.jenkins.io/war/latest/jenkins.war

Create Project Home

We want to keep jenkins and all related files and services in one place.

So, lets create the folder jenkins whereever you want.

First create main folder (we will rever to this as JENKINS_ROOT)

mkdir /home/jenkins

Next, we create the folder JENKINS_HOME. This will the the home directory for the jenkins serice.

mkdir /users/jenkins/home

Remember this folders

export JENKINS_ROOT=/home/jenkins
export JENKINS_OME=$JENKINS_ROOT/home

Start Jenkins

java -jar jenkins.war –enable-future-java

Starting Jenkins this way, you will see all log messages on the console.

At this step, the importen messages are the initial admin password:

2020-02-28 16:50:00.749+0000 [id=32]	INFO	jenkins.install.SetupWizard#init:

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

6c408145cc964f72ab45cd80e247fa2d

This may also be found at: /home/jenkins/home(secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

2020-02-28 16:50:05.848+0000 [id=57]	INFO	h.m.DownloadService$Downloadable#load: Obtained the updated data file for hudson.tasks.Maven.MavenInstaller

Start browser and install plugins, create user

$ chrome localhost://8080

Shell access to Jenkins docker

$ docker exec -it jenkins-tutorials bash

Create a Pipeline for a simple Maven Project

Clone the sample maven app

git clone https://github.com/jenkins-docs/simple-java-maven-app

If you want to create a new maven app, you could start with the following command

mvn archetype:generate
        -DgroupId=com.jcg.maven 
        -DartifactId=HelloWorld 
        -DarchetypeArtifactId=maven-archetype-quickstart 
        -DinteractiveMode=false

cd HelloWorld

Install and Build package

mvm clean install

mvn package

Run your app

java -cp target/MavenHelloWorldProject-1.0-SNAPSHOT.jar  com.jcg.maven.App

Troubleshooting

No such DSL method ‘withMaven’ found among steps

This means you don’t have withMaven as an available DSL method. Most of the time this means you don’t have a plugin installed. In this case, the Pipeline Maven Plugin is required. https://wiki.jenkins.io/display/JENKINS/Pipeline+Maven+Plugin

Links

Local Continuous Delivery Environment With Docker and Jenkins

Additional Readings

Using Oracle Java or OpenJDK.

Install Java on Mac OS with Homebrew

$ brew tap AdoptOpenJDK/openjdk
brew cask install adoptopenjdk8

Install Jenkins with Homebrew on Mac OS

brew install jenkins-lts
brew services start jenkins-lts

Install Jenkins with Docker

$ docker run --rm -u root -p 8080:8080  -p 50000:50000 
  -v jenkins-data:/var/jenkins_home 
  -v /var/run/docker.sock:/var/run/docker.sock 
  -v "$HOME":/home 
  jenkinsci/blueocean

Zsh | Cookbook

Useful tips

Speed-up zsh start

Depending on the way, you install zsh, the installation process clones git-repositories to your home folder $HOME.

Starting zsh does at one point check files git ‘git ls-files’. So, if you have a lot of files and folders in your home directory, this will take some time.

If you want to speedup the start, create a .gitignore file in your home an include all files with not relations to zsh, e.g. .npm, .ssh or .Trash.

Customize Zsh Prompt

Powerlevel9k

Installation on mac OS

Install

$ brew tap sambadevi/powerlevel9k
$ brew install powerlevel9k

Add Themes to .zshrc

. /usr/local/opt/powerlevel9k/powerlevel9k.zsh-theme

Install on macx OS to use in Oh-My-Zsh

To install this theme for use in Oh-My-Zsh, clone this repository into your OMZ custom/themesdirectory.

$ git clone https://github.com/bhilburn/powerlevel9k.git ~/.oh-my-zsh/custom/themes/powerlevel9k

You then need to select this theme in your ~/.zshrc:

ZSH_THEME="powerlevel9k/powerlevel9k"

Links and Resources

Zsh with Powerlevel9K — Power up your terminal‘s colour scheme and productivity level

Git | Cookbook

Github hints

Repository — Quick setup

Clone repository

.. or create a new repository on the command line

echo "# Init " >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin <url>
git push -u origin master

…or push an existing repository from the command line

git remote add origin git@github.com:<username>/<repository>.git
git push -u origin master

Merge branch with master

Merging via command line

Step 1: From your project repository, bring in the changes and test.

git fetch origin
git checkout -b develop origin/develop
git merge master

Step 2: Merge the changes and update on GitHub.

git checkout master
git merge --no-ff develop
git push origin master

Useful commands

To show information about a remote, for example if tracked branches are up-to-date:

git remote show origin
git remote -v
git remote add <shortname> <url>
git fetch <remote>
git push <remote> <branch>
git remote show <remote>
git remote rename <old> <new>
git remote remove <name>

To show log messages of the changes between branches:

git log origin/master ^master

Show log graph

git log --pretty=format:



To show differences between branches:

$ git diff master origin/master

Show , what git pull will doing

$ git fetch && git diff HEAD..@{u}

Or add the command to ~/.gitconfig file:

[alias]
        diffpull=!git fetch && git diff HEAD..@{u}

Run this to see how git diff resolution works

git rev-parse origin

Delete remote branch

git clone <repository> master
cd master
git push origin --delete feature-2.01.03

Show log

git log --oneline --graph --all --decorate

Undo commit

git commit --amend

Unstaging a staged file

git reset HEAD <filename>

Unmodifying a Modified File

$ git checkout -- <filename>

Retrieve last modification date

git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format=



Git Configuration

Show location of configuration files

git config --list --show-origin

This dows not work, if you have set the environment var GIT_CONFIG. In this case, do

unset GIT_CONFIG
git config --global --list

Edit config files

git config --edit --global
git config --edit --system
DESCRIPTIONGIT COMMAND
Configure the author name to be used with your commits.git config --global user.name "XXX"
Configure the author email address to be used with your commitsgit config --global user.email xxx@example.com
Will remove user credential details from the repositorygit config --local credential.helper ""
git config —show-origin
List all currently configured remote repository URLsgit remote -v
If you haven’t connected your local repository to a remote server, To add a remote server to a local repositorygit remote add origin <repo_url>

Git Commit and Push

DESCRIPTIONGIT COMMAND
Create a file name README.md with Readme content contentecho "Readme content" >> README.md
List the files you’ve changed and those you still need to add or commitgit status
Add all or one file to staginggit add . OR git add file_name
Commit changes to head with messagegit commit -m 'message'
Commit any files you’ve added with git add, and also commit any files you’ve changed since thengit commit -a
Send all commits from local repository to remote repositorygit push
Do a git push and sets the default remote branch for the current local branch. So any future git pull command will attempt to bring in commits from the <remote-branch>into the current local branchgit push -u <remote-branch>
Send changes to the master branch of your remote repositorygit push origin master
Push a specific branch to your remote repositorygit push origin <branch_name>
Push all branches to your remote repositorygit push --all origin

Working with the Git Workflow

The following steps are based on a branching model, described here.

Name Beschreibung
master
hotfixes
release
develop
feature

Working with branches

Create branch ‘develop’

$ git clone git@github.com:<USER>/<REPO>.git develop
$ cd develop
$ git checkout -b develop
$ git push --set-upstream origin develop

Create branch ‘feature-xxx’

We dont’t want do clone the whole repository, but only the files needed for the feature

$ git clone -b develop -n --depth 1 git@github.com:<USER>/<REPO>.git feature-2.2.0
$ cd feature-2.2.0

Branch löschen

$ git push origin -delete hotfix-1.2.1-compress-data

Workflow – Cheatsheet

Working with branches

How to rename git local and remote branches

Check out branch with old name

git checkout feature-2.1.2

Rename branch

git branch -m feature-2.01.02

Checkin branch with new name

git push origin :feature-2.1.2 feature-2.01.02

1. Rename your local branch.

If you have named a branch incorrectly AND pushed this to the remote repository follow these steps before any other developers get a chance to jump on you and give you shit for not correctly following naming conventions.

If you are on the branch you want to rename:

git branch -m new-name

If you are on a different branch:

git branch -m old-name new-name

2. Delete the old-name remote branch and push the new-name local branch.

git push origin :old-name new-name

3. Reset the upstream branch for the new-name local branch.Switch to the branch and then:

git push origin -u new-name

Or you as a fast way to do that, you can use these 3 steps: command in your terminal

git branch -m old_branch new_branch         # Rename branch locally    
git push origin :old_branch                 # Delete old branch    
git push --set-upstream origin new_branch   # Push new branch, set local branch to track new remote
Neues Feature erstellen
Repository clonen$ git checkout -b feature-1.2.2 develop
Änderungen durchführen
Änderungen einchecken$ git checkout develop
$ git merge –no-ff feature-1.2.2
$ git branch -d feature-1.2.2
$ git push origin develop
Neuen Hotfix erstelllen
Repository auschecken$ git checkout -b hotfix-1.2.1 master
Änderungen durchführen
Änderungen einchecken$ git commit -a -m “hotfix: hotfix-1.2.1| compress mart”
Hotfix beenden$ git checkout master
$ git merge –no-ff hotfix-1.2.1
$ git tag -a 1.2.1
Hotfix in Master einchecken$ git checkout develop
$ git merge –no-ff hotfix-1.2.1  
Hotfix Branch entfernen$ git branch -d hotfix-1.2.1
Neues Release erstellen:
Repository clonen$ git checkout -b release-1.2 develop
Änderungen durchführen
Änderungen einchecken$ git commit -a -m “release: changes for release 1.2”
Release beenden$ git checkout master
$ git merge –no-ff release-1.2
$ git tag -a 1.2

Git Flow

Initialize

Start using git-flow by initializing it inside an existing git repository:

$ git flow init

Start a new feature

Development of new features starting from the ‘develop’ branch.

git flow feature start MYFEATURE

Finish up a feature

Finish the development of a feature. This action performs the following

git flow feature finish MYFEATURE

Publish a feature

Publish a feature to the remote server so it can be used by other users.

git flow feature publish MYFEATURE

Getting a published feature

Get a feature published by another user.

git flow feature pull origin MYFEATURE

You can track a feature on origin by using

git flow feature track MYFEATURE

Start a release

git flow release start RELEASE [BASE]

It’s wise to publish the release branch after creating it to allow release commits by other developers. Do it similar to feature publishing with the command:

git flow release publish RELEASE

(You can track a remote release with the 
git flow release track RELEASEcommand)

Finish up a release

git flow release finish RELEASE

Don’t forget to push your tags with git push origin --tags

Hotfixes

git flow hotfix start VERSION [BASENAME]

Finish a hotfix

git flow hotfix finish VERSION

Usefull commands

basic commandsdescription
git init
git status  [ -s ]status of files and local repo
git ls-filesshow files which are tracked by git
git log [ –oneline ]
git log [–oneline –graph –decorate –all]
shows commit history
git add <changed file>
git add .git add -u
add single file to indexadd all files from the workspace to indexstage current workspace into index to cleanup inconsistencies
git commit [ -m ‘message’ ]commit into local repo only
git push -u origin masterpush the repo from local to remote repo
git help [option]get help page for specific options
git config –global alias.bla “command”
git bla [– <filename>]
set alias bla to a specific commandexec alias (for specific file)
git mv fileA fileB
git commit -m “…..”
rename fileA to fileBand commit
git rm fileC
git commit -m “…..”
delete fileCand commit
advanced commandsdescription
git reset HEAD <filename>undo changes from index back to workspace
git checkout <filename>
git checkout master
git checkout <branchname>
checkout single file from local repo to workspacecheckout/switch to the master branchcheckout/switch to another branch
git checkout -b <new branchname>
git branch <new branchname>
create new branch and switch to it immediatelycreate new branch in the background, doesn’t switch to it
git branchshows all available branches
git diff
git difftool
show differences of local and committed file
shows diff in vimdiff
git merge <other branch>
git mergetool
merge other branch into master (current branch)manage the different files in vimdiff
git branch -d <branchname>delete branch (does NOT include merge)
git branch -m <new name>rename a
$ git diff master..developmentcompare two branches
git tag <mytag>
git tag -a v1.0 -m “description”
git show v1.0
add an additional label/tag to a branchannotation tag with release informationshows details of tag v1.0
git stash
git reset <ID> [–soft | –mixed | –hard]
git reflog ….
git fetch ….update local repo with changes from remote repo. (non destructive)
git pull …update local repo with changes from remote repo. it does effectively a fetch and merge in one command
git clone https://<username>:<token>@github.com/<organisation-space>/<repository>
download the remote repo into local workspace
git remote -v
git remote show origin
shows url of remote reposhows detail infos of a remote repo
.gitignorecontains filename to exclude from git

Git Workflow

Release

Creating a release branch

Release branches are created from the develop branch. For example, say version 1.1.5 is the current production release and we have a big release coming up. The state of developis ready for the “next release” and we have decided that this will become version 1.2 (rather than 1.1.6 or 2.0). So we branch off and give the release branch a name reflecting the new version number:

$ git checkout -b release-1.2 develop

After creating a new branch and switching to it, we bump the version number. Here, bump-version.sh is a fictional shell script that changes some files in the working copy to reflect the new version. (This can of course be a manual change—the point being that some files change.) Then, the bumped version number is committed.

This new branch may exist there for a while, until the release may be rolled out definitely. During that time, bug fixes may be applied in this branch (rather than on the developbranch). Adding large new features here is strictly prohibited. They must be merged into develop, and therefore, wait for the next big release.

$ ./bump-version.sh 1.2<br>
$ git commit -a -m "Version 1.2"

Finishing a release branch 

$ git checkout master
$ git merge --no-ff release-1.2
$ git tag -a 1.2
$ git checkout develop
$ git merge --no-ff release-1.2
$ git branch -d release-1.2

When the state of the release branch is ready to become a real release, some actions need to be carried out.

First, the release branch is merged into master (since every commit on master is a new release by definition, remember).

Next, that commit on master must be tagged for easy future reference to this historical version.

Finally, the changes made on the release branch need to be merged back into develop, so that future releases also contain these bug fixes.

$ git checkout master
$ git merge --no-ff release-1.2
$ git tag -a 1.2

The release is now done, and tagged for future reference.

To keep the changes made in the release branch, we need to merge those back into develop, though. In Git:

$ git checkout develop
$ git merge --no-ff release-1.2

This step may well lead to a merge conflict (probably even, since we have changed the version number). If so, fix it and commit.

Now we are really done and the release branch may be removed, since we don’t need it anymore:

$ git branch -d release-1.2

Feature

$ git checkout -b myfeature develop
$ .. do changes...

$ git checkout develop
$ git merge --no-ff myfeature
$ git branch -d myfeature
$ git push origin develop

Creating a feature branch 

When starting work on a new feature, branch off from the develop branch.

$ git checkout -b myfeature develop
Switched to a new branch "myfeature"

Incorporating a finished feature on develop 

Finished features may be merged into the develop branch to definitely add them to the upcoming release:

$ git checkout develop<
$ git merge --no-ff myfeature
$ git branch -d myfeature
$ git push origin develop 

The --no-ff flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature.

In the latter case, it is impossible to see from the Git history which of the commit objects together have implemented a feature—you would have to manually read all the log messages. Reverting a whole feature (i.e. a group of commits), is a true headache in the latter situation, whereas it is easily done if the --no-ff flag was used.

Hotfix

$ git checkout -b hotfix-1.2.1 master
$ ... do changes ... 
$ git commit -a -m "Hotfix Version 1.2.1"
$ .. fix bug
$ git commit -m "Fixed severe production problem"

$ git checkout master
$ git merge --no-ff hotfix-1.2.1
$ git tag -a 1.2.1

# incude hotfix into develop
$ git checkout develop
$ git merge --no-ff hotfix-1.2.1

# finally, remove hotfix branch
$ git branch -d hotfix-1.2.1

Troubleshooting

Debugging Github Errors

export GIT_TRACE_PACKET=1
export GIT_TRACE=1
export GIT_CURL_VERBOSE=1

Error Message: Your local changes to the following files would be overwritten by merge:

error: Your local changes to the following files would be overwritten by merge:<br>
        README.md<br>
Please commit your changes or stash them before you merge.

Solution:

$ git fetch origin master
$ git diff origin/master -- [local-path]
$ git add [local-path]
$ gt commit -m "change: in file [local-path]"

fatal: sha1 file ‘<stdout>’ write error: Broken Pipe

When using ssh to connect to the repositoriy, sometime, you got a timeout if you push to many files or if the files are to big

One possible Solution

Configure ssh to use the following value

~/.ssh/config
Host *
     ServerAliveInterval 30
     ServerAliveCountMax 4

git clone: file name to long on windows

git config --system core.longpaths true

git config –global user.email “some@email.com” throws “error: only one config file at a time.

Try to unset GIT_CONFIG and then list your global config with

unset GIT_CONFIG
git config --global --list

Other Links

Useful Git commands for everyday use

10 useful Git commands you always need

Most useful Git commands

Git Cheat Sheet

Useful Git commands

Using local Filesystem as Respository-Master

Preparation

Set environment variables for easy typing

$ REPOS=$HOME/repos

Create Repository

$ mkdir $REPOS
$ cd    $REPOS
$ git init --bare src

Create src folder

$ mkdir $HOME/entw
$ cd    $HOME/entw
$ mkdir src
$ cd    src
$ git init

Create some content

$ touch README.md
$ git add -A
$ git commit -m "initial commit"
$ git remote add origin $REPOS/src
$ git remote -v
$ git push --set-upstream origin master
$ git push origin master

Create clone

$ mkdir $HOME/test
$ cd    $HOME/test
$ git clone $HOME/repos/src
$ cd src
$ ls -al
total 0
drwxr-xr-x   4 user  wheel  128 19 Mär 18:48 .
drwxr-xr-x   3 user  wheel   96 19 Mär 18:48 ..
drwxr-xr-x  12 user  wheel  384 19 Mär 18:48 .git
-rw-r--r--   1 user  wheel    0 19 Mär 18:48 README.md

You will notice, that the file README.md is empty. Because it was ony created with touch.

Add some content to source repository

$ cd $HOME/entw/src
$ echo "# This is the README.md from ENTW" >README.md
$ touch git_update
$ touch git_push
$ ls -al
total 16
drwxr-xr-x   6 user  wheel  192 19 Mär 18:53 .
drwxr-xr-x   3 user  wheel   96 19 Mär 18:43 ..
drwxr-xr-x  12 user  wheel  384 19 Mär 18:47 .git
-rw-r--r--   1 user  wheel   34 19 Mär 18:52 README.md
-rw-r--r--   1 user  wheel    0 19 Mär 18:53 git_push
-rw-r--r--   1 user  wheel    0 19 Mär 18:53 git_update

Add changes to repository

$ git add -A
$ git commit -m "-"
[master 106b27a] -
 3 files changed, 1 insertion(+)
 create mode 100644 git_push
 create mode 100644 git_update
$ git push --set-upstream origin master
Objekte aufzählen: 5, Fertig.
Zähle Objekte: 100% (5/5), Fertig.
Delta-Kompression verwendet bis zu 8 Threads.
Komprimiere Objekte: 100% (2/2), Fertig.
Schreibe Objekte: 100% (3/3), 320 bytes | 320.00 KiB/s, Fertig.
Gesamt 3 (Delta 0), Wiederverwendet 0 (Delta 0)
To ..../repos/src
   7ed6d3b..106b27a  master -> master
Branch 'master' folgt nun Remote-Branch 'master' von 'origin'.

Update clone

$ cd $OME/test/src
$ git pull
# git fetch   # This updates 'remote' portion of local repo. 
# git reset --hard origin/<your-working-branch>
remote: Objekte aufzählen: 5, Fertig.
remote: Zähle Objekte: 100% (5/5), Fertig.
remote: Komprimiere Objekte: 100% (2/2), Fertig.
remote: Gesamt 3 (Delta 0), Wiederverwendet 0 (Delta 0)
Entpacke Objekte: 100% (3/3), Fertig.
Von .../repos/src
   7ed6d3b..106b27a  master     -> origin/master
$ git merge origin/master
Aktualisiere 7ed6d3b..106b27a
Fast-forward
 README.md  | 1 +
 git_push   | 0
 git_update | 0
 3 files changed, 1 insertion(+)
 create mode 100644 git_push
 create mode 100644 git_update
$ ls -al
total 16
drwxr-xr-x   6 user  wheel  192 19 Mär 19:02 .
drwxr-xr-x   3 user  wheel   96 19 Mär 18:48 ..
drwxr-xr-x  14 user  wheel  448 19 Mär 19:02 .git
-rw-r--r--   1 user  wheel   34 19 Mär 19:02 README.md
-rw-r--r--   1 user  wheel    0 19 Mär 19:02 git_push
-rw-r--r--   1 user  wheel    0 19 Mär 19:02 git_update

TODO

See changes before pulling from remote git repositoryf

# fetch the changes from the remote
git fetch origin
# show commit logs of changes
git log master..origin/master
# show diffs of changes
git diff master..origin/master
# apply the changes by merge..
git merge origin/master
# .. or just pull the changes
git pull

You want to push your local files to remote files

git push -f <remote> <branch>
git push -f origin master

Configure Hooks

git config --global core.hooksPath .githooks
mkdir .githooks
cp .git/hooks/* .githooks

commit-msg

#!/bin/sh
#

NAME=$(git rev-parse --abbrev-ref HEAD) 
DESCRIPTION=$(git config branch."$NAME".description)

echo "$NAME"': '$(cat "$1") > "$1"
if [ -n "$DESCRIPTION" ] 
then
   echo "" >> "$1"
   echo $DESCRIPTION >> "$1"
fi

prepare-commit

#!/bin/sh
#

COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3

branchPath=$(git symbolic-ref -q HEAD)
branchName=${branchPath##*/}


if [ -n "$branchName" ]; then
    echo "$branchName | $(cat $1)" > $1
fi
file=$(git config hooks.versionfilename)
if [[ -z $file ]]
then
  file=".version"
fi

# Version number
echo "$(git rev-parse --abbrev-ref HEAD): $(git describe --tags --long)" >$file

exec git add $file

pre-commit

#!/bin/sh

_BRANCHPATH=$(git symbolic-ref -q HEAD)
_BRANCHNAME=${_BRANCHPATH##*/}

_TIMESTAMP="$(date '

echo "HOOK      : $0"
echo "PARAMETER : '$*''"
echo "BRANCHPATH: $_BRANCHPATH"
echo "BRANCHNAME: $_BRANCHNAME"

LOG() {
    [[ "$GIT_COMMIT_DETAILED_LOGGING" == "YES" ]] && echo "LOG: $*"
}

REPLACE()
{
   local _TYP;   _TYP="$1"; shift
   local _TAG;   _TAG="$1"; shift
   local _WITH; _WITH="$1"; shift
   local _FILE; _FILE="$1"; shift

   case "$_TYP" in
      PYTHON)   perl -pi -e 's/(\s*)(__DEPLOY_'${_TAG}'\s*=\s*)(".+")/${1}${2}"'"${_WITH}"'"/' "${_FILE}"
                ;;
      *)        LOG "Undefined typ '$TYP' for file $_FILE"
                ;;
   esac

   rm -f "${_FILE}.bak"
}

LOG "working on branch $_BRANCH"

for _FILE in $(git diff-index --name-status --cached HEAD | grep -v ^D | cut -c3-)
do
    LOG "checking: $_FILE"

    # Only examine known text files
    if [[ "$_FILE" =~ [.](py)$ ]]; then
        LOG "patching: $_FILE"

        REPLACE PYTHON TAG       "$_BRANCHNAME" "$_FILE"
        REPLACE PYTHON TIMESTAMP "$_TIMESTAMP"  "$_FILE"
    fi
done

Get Information

git rev-parse –abbrev-ref HEADget branch namefeature/add-new-content
git symbolic-ref -q HEADrefs/heads/feature/add-new-content
git rev-parse –show-toplevelshow current path of git repository

Config

Change Github repository for local clone

cd <original repository>
git remote set-url origin https://github.com/<new git user>/<new project name>
git push -u origin master

CR/LF Mapping

git config core.autocrlf true
git config --global core.safecrlf false

Create Release

#!/bin/bash

if [ $# -ne 1 ]; then
  echo "Syntax: release [VERSION]"
  exit 1
fi

VERSION=$1

# Create release
git flow release start $VERSION || exit 1
GIT_MERGE_AUTOEDIT=no git flow release finish -m $VERSION $VERSION

# Publish release
git push origin HEAD --tags

# Merge release into develop
git checkout develop
git merge master

SAS | Using Git and multi-repository environments

Using Git Hooks

$ git config --global core.hooksPath .githooks

Anhang: .githooks

prepare-commit-msg

#!/bin/bash
#

COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3

branchPath=$(git symbolic-ref -q HEAD)
branchName=${branchPath##*/}


if [ -n "$branchName" ]; then
    echo "$branchName | $(cat $1)" > $1
fi

pre-commit

#!/bin/bash
#

_BRANCHPATH=$(git symbolic-ref -q HEAD)
_BRANCH=${_BRANCHPATH##*/}

_TIMESTAMP="$(date '

LOG() {
        if [[ "$GIT_COMMIT_DETAILED_LOGGING" == "YES" ]]; then
                echo "LOG: $*"
        fi
}

REPLACE()
{
   local _TYP;   _TYP="$1"; shift
   local _TAG;   _TAG="$1"; shift
   local _WITH; _WITH="$1"; shift
   local _FILE; _FILE="$1"; shift

   case "$_TYP" in
      SAS)       # 
                 perl -pi -e 's/(.*)
                ;;
      CUSTOMER) # /* __DEPLOY_TAG =
                perl -pi -e 's/(\/\*\s*)('"__DEPLOY_$_TAG"'\s*=\s*)(.*$)/${1}${2
                ;;
      *)        LOG "Undefined typ '$TYP' for file $_FILE"
                ;;
   esac

   rm -f "${_FILE}.bak"
}

LOG "working on branch $_BRANCH"

for _FILE in $(git diff-index --name-status --cached HEAD | grep -v ^D | cut -c3-)
do
        LOG "checking file $_FILE"

        # Only examine known text files
        if [[ "$_FILE" =~ [.](sas)$ ]]; then
                LOG "working on file $_FILE"
                REPLACE SAS TAG       "$_BRANCH"    "$_FILE"
                REPLACE SAS TIMESTAMP "$_TIMESTAMP" "$_FILE"
        fi

        if [[ "$_FILE" =~ ^MA03 ]]; then
                LOG "working on bihis-customer script  $_FILE"
                REPLACE CUSTOMER TAG       "$_BRANCH"    "$_FILE"
                REPLACE CUSTOMER TIMESTAMP "$_TIMESTAMP" "$_FILE"
        fi
done

Bash | Cookbook

Configure Bash Environment

Using Bash Completion

Add git completion

Download git-completion.bash to $HOME/etc

$ mkdir $HOME/etc
$ cd $HOME/etc
$ wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash

Add git-prompt to .bashrc

. $HOME/etc/git-completion.sh

Add completion for Makefiles

Add this to .bashrc

complete -W "`grep -oE '^[a-zA-Z0-9_.-]+:([^=]|$)' ?akefile | sed 's/[^a-zA-Z0-9_.-]*$//'`" make

Customize Bash prompt

Add git repository/branch to prompt

Download git-prompt.sh to $HOME/etc

$ mkdir -p $HOME/etc
$ cd $HOME/etc
$ wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh

Add git-prompt to .bashrc

. $HOME/etc/git-prompt.sh

Configure prompt to display git branch

export PS1='[\033[33;1m]\w[\033[m] [\033[32m]$(__git_ps1 " 



Writing Bash Scripts

Set vi commands in bash-script

Parsing Parameter

$ brew install gnu-getopt

Bash Script Template

#------------------------------------------------------------------------------------------
CMD_GETOPT=/usr/local/opt/gnu-getopt/bin/getopt

S_OPTS="vdm:"
L_OPTS="verbose,debug,versions,install:,init:"

OPTS=$($CMD_GETOPT --options "$S_OPTS"--longoptions "$L_OPTS"    -- "$@")

eval set $OPTS
shift

while [[ $# -gt 0 ]]; do
    echo "Param 1: '$1'"

    case "$1" in
        -v | --verbose)    VERBOSE=true;                 ;;
        -d | --debug)      DEBUGLEVEL="$2";  shift       ;;

        --versions)        MODE=GETVERSIONS              ;;
        --install)         TYPE="$2";        shift
                           MODE=INSTALL                  ;;

        --init)            MODE=INIT                     ;;

        --)                                  shift; break;;
        * )                                         break;;
    esac

    shift
done

Show progress with a spinner

#!/bin/bash
 
COMMAND="${1^^}"
 
SYMBOL_PASS="$(printf '\e[0;32m\xe2\x9c\x94\e[0m')"
SPINNER_STATE='\|/-'
 
spinner()
{
        local _lastpos=$((${#SPINNER_STATE}-1))
        SPINNER_STATE="${SPINNER_STATE:$_lastpos:1}${SPINNER_STATE:0:$_lastpos}"
 
        printf 
}
 
#---------------------------------------------------------------------------------------------------
#
#---------------------------------------------------------------------------------------------------
if [[ "$COMMAND" = "STEP1" ]]; then
        printf 
        _LASTDATE=
        for _LINE in *.csv
        do
                _FILE="$(basename $_LINE)"
                _CURRDATE=${_FILE:19:8}
                rm    -rf       $_CURRDATE
                mkdir -p        $_CURRDATE
                cp       $_LINE $_CURRDATE
 
                if [[ "$_CURRDATE" = "$_LASTDATE" ]]; then
                        spinner
                else
                        printf "${SYMBOL_PASS}\n${_CURRDATE}: "
                fi
 
                _LASTDATE=$_CURRDATE
        done
        printf "\n"
fi

Github | Einstieg

Github ist eine Webseite, die es ermöglicht, gemeinsam an einem Softwareprojekt zu arbeiten.

Zusätzlich gibt es eine Versionsverwaltung: es wird also jede Änderung mit protokolliert, so das diese überprüft und rückgängig gemacht werden kann.

Einstieg

Der Arbeitsalltag eines Entwicklers, der Github nutzt sieht meistens wie folgt aus

  • er erstellt einmalig ein Github Konto
  • er richtet ein Repository ein, in dem er seine Programme speichert und verwaltet
  • das Repository wird “ausgecheckt“. Dadurch wird eine lokale Kopie auf der Festplatte angelegt
  • er arbeitet und programmiert in dieser lokalen Kopie
  • wenn er mit den Änderungen fertig ist, dann wird das Repository “eingecheckt“. Alle Änderungen sind dann wieder im Repository auf dem GibHub server gespeichert.

Mehr über das Arbeiten mit GibHub kann man hier und hier nachlesen.

Einrichten eines Github-Konto

Schritt 1: notwendige Informationen eingeben

Öffne deinen Browser und geh auf die Seite https://github.com/join

Gibt dann die notwendigen Informationen ein

  • Benutzername
  • Email
  • Passwort

Schritt 2: Verifizieren, das ein Mensch das Konto einrichtet

Klick auf die Pfeile, bis das Bild in der Mitte an der richtigen Stellung steht.

Klick dann auf Done

Schritt 4: Konto einrichten

Klick auf die Schaltfläche Create an account

Schritt 4: Kontotyp einrichten – ein kostenloses Konto

Behalte die Voreinstellung Free bei und klick auf Continue

Schritt 5: Überspringen der letzten Eingaben

Wähle hier aus, was Du selbst angeben möchtest und klick auf Submit.

Oder überspringe diese Schritt und klick auch skip this step

Schritt 6: Bestätigungslink öffnen

Schau in dein Postfach, du solltest eine Email erhalten haben. Klick auf den Bestätigungslink, so das dein Konto eingerichtet wird.

Erstes Repository einrichten

Melde dich bei deinem Github-Konto an, falls Du es noch nicht bist

Schritt 1: Repository erstellen

Auf der Startseite klick auf die Schaltfläche Start a project

Schritt 2. Neues Repository

Schritt 3: Informationen über das Repository

Gib den Namen ein

home

Gib eine Beschreibung ein:

Webseite meines Repositories

Wähle den Typ

Public

Selektiere die Option

Initialize this repository with a README

Klick auf die Schaltfläche

Create repository

Fertig. Das erste Repository ist erstellt!

Arbeiten mit den Repository

Vorbereitung

Als erstes ermitteln wir die URL, um das Repository auszuchecken

Die URL hat immer den gleiche Aufbau und lautet hier:

<a href="https://github.com/ionic-testaccount/home.git">https://github.com/ionic-testaccount/home.git</a>

Der allgemeien Aufbau ist:

<a href="https://github.com/<USERNAME>/<REPONAME>home.git">https://github.com/<USERNAME>/<REPONAME>.git</a>

Auschecken des Repositories

Ausgecheckt wird das Repository mit dem Kommando git clone. Man erstellt einen “Clone” der Repositories auf dem lokalen Rechner. Das Repository wird in einem Ordner erstellt, der den Namen des Repositories erhält:

Änderungen durchführen

Im nächsten Schritt erfolgt das Arbeiten mit dem Repository. Hier werden die gewünschten Änderungen an den Dateien durchgeführt.

Beispielhaft erstellen wir eine neue Datei TODO.md:

Status anzeigen

Mit dem Kommando git status können wir die Änderungen anzeigen lassen. Damit sehen wir, was sich im Vergleich zum Repository auf Github geändert hat.

In unserem Beispiel wird die neue Datei angezeigt als Untracked file:

Änderungen übernehmen

Mit Hilfe der Kommandos git add wird die durchgeführten Änderungen “vorgemerkt” für die Aufnahme in das Repository.

Das eigentliche hinzufügen erfolgt durch das Bestätigen der Änderungen: mit dem Kommando git commit. Durch den Parameter -m wird eine Beschreibung der Änderung hinzugefügt.

Einchecken des Repositories

Zum Abschluss wollen wir die bestätigten Änderungen in das Repository hochladen.

Hier benötigen wir natürlich die erforderlichen Rechte.

Wir erhalten diese, in dem wir unseren Benutzernamen mit angeben. Wir passen dazu die URL des Repositories an:

Jetzt erfolgt das Hochladen mit git push. Es muss nur noch das Passwort angegeben werden:

Der abschliessende Status zeigt, das alle Änderungen übernommen sind und das lokale Repository auf dem gleiche Stand ist, also “clean”

Repository auf Github prüfen

Ein Blick auf die Webseite unseres Repositories zeigt, das die Änderungen übernommen wurde. Wir sehen die neue Datei mit den von uns verwendeten Kommentar.

Ionic | Create a simple Calculator

Sources for this tutorial are here.

Preparation

Clone the example

git clone https://github.com/ionic4-toolbox/App-Calculator.git

Starting from new

Before starting, make sure that you are using the current ionic version.If you are new to ionic , then look here for an installation guide.

npm -g install ionic@latest

Create App

ionic start Calculator sidemenu --type angular --no-link --no-git
cd Calculator

Add a new page for our calculator

ionic generate page Calculator

Add new page to sidemenu

Add link to page in app.components.ts file

  public appPages = [
    { title: 'Home', url: '/home', icon: 'home' },
    { title: 'List', url: '/list', icon: 'list' },
    { title: 'Calculator', url: '/calculator', icon: 'grid'
    }
  ];

Add calculation logic to typescript file

4public appPages = [
    { title: 'Home', url: '/home', icon: 'home' },
    { title: 'List', url: '/list', icon: 'list' },
    { title: 'Calculator', url: '/calculator', icon: 'grid' }
];

Add html layout

The layout of our page consists of a header row containing the result and 4 rows containing the buttons of our calculator.

Header
Row 1
Row 2
Row 3

Each row for our keys is build with 5 columns.

Header
Row1, Col1Row1, Col2Row1, Col3Row1, Col4Row1, Col5
Row2, Col1Row2, Col2Row2, Col3Row2, Col4Row2, Col5
Row3, Col1Row3, Col2Row3, Col3Row3, Col4Row3, Col5
Row4, Col1Row4, Col2Row4, Col3Row4, Col4Row4, Col5

Add within the table cells, we place our buttons

Header
789×÷
456+
123x2√x
C0,1/x=

We implement our layout with div’s instead of a html table.

So every row is a

<div class="row">
...
</div>

And within the row we define our buttons also as divs

<div class="number">
   <span (click)="btnClicked('4')">4</span>
   <span (click)="btnClicked('5')">5</span>
   <span (click)="btnClicked('6')">6</span>
</div>
<div class="symbol"><span (click)="btnClicked('+')">+</span></div>
<div class="symbol"><span (click)="btnClicked('-')">-</span></div>

The final html layout looks like this:

<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-menu-button></ion-menu-button>
    </ion-buttons>
    <ion-title>Rechner</ion-title>
  </ion-toolbar>
</ion-header>
<ion-content>
  <div class="calculator">
    <div class="header">
      <div class="window"></div>
      <div class="input"><span>
          <ion-input type="text" placeholder="0" name="display"
                     [(ngModel)]="result">
          </ion-input>
        </span></div>
    </div>
    <div class="keys">
      <div class="row">
        <div class="number">
          <span (click)="btnClicked('7')">7</span>
          <span (click)="btnClicked('8')">8</span>
          <span (click)="btnClicked('9')">9</span>
        </div>
        <div class="symbol"><span (click)="btnClicked('*')">×</span></div>
        <div class="symbol"><span (click)="btnClicked('/')">÷</span></div>
      </div>
      <div class="row">
        <div class="number">
          <span (click)="btnClicked('4')">4</span>
          <span (click)="btnClicked('5')">5</span>
          <span (click)="btnClicked('6')">6</span>
        </div>
        <div class="symbol"><span (click)="btnClicked('+')">+</span></div>
        <div class="symbol"><span (click)="btnClicked('-')">-</span></div>
      </div>
      <div class="row">
        <div class="number">
          <span (click)="btnClicked('1')">1</span>
          <span (click)="btnClicked('2')">2</span>
          <span (click)="btnClicked('3')">3</span>
        </div>
        <div class="symbol">
          <span (click)="btnClicked('square')">x<sup>2</sup></span>
        </div>
        <div class="symbol">
          <span (click)="btnClicked('squareroot')">√x</span>
        </div>
      </div>
      <div class="row">
        <div class="number">
          <span class=dull (click)="btnClicked('C')">C</span>
          <span (click)="btnClicked('0')">0</span>
          <span (click)="btnClicked(',')">,</span>
        </div>
        <div class="symbol">
          <span (click)="btnClicked('reciproc')">1/x</span>
        </div>
        <div class="symbol action">
          <span (click)="btnClicked('=')">=</span>
        </div>
      </div>
    </div>
  </div>
</ion-content>

Add css definitions

html,
body {
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    font-family: "Trebuchet MS", Helvetica, sans-serif;
    font-size: 28px;
}
body {
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #f5f5f5;
}
.calculator {
    margin: 20px;
    widows: 100px;
    border-radius: 10px;
    box-shadow: 0 25px 60px -10px rgba(0, 0, 0, 0.5);
    .header {
        background-color: #000;
        height: 120px;
        border-radius: 10px 10px 0 0;
        .window {
            height: 15px;
            display: flex;
            justify-content: flex-start;
            padding: 10px;
            span {
                width: 10px;
                height: 10px;
                border-radius: 50%;
                margin-right: 5px;
                cursor: pointer;
                &.red {
                    background-color: #ff5252;
                }
                &.yellow {
                    background-color: #f5a623;
                }
                &.green {
                    background-color: #73c21d;
                }
            }
        }
        .input {
            background-color: #ff0300;
            color: #ffffff;
            padding: 10px 30px;
            font-size: 28px;
            span {
                text-align: right;
                color: #ffffff;
            }
        }
    }
    .keys {
        background: linear-gradient(135deg, #3a3a3a, #000000);
        height: 280px;
        border-radius: 0 0 10px 10px;
        font-size: 24px;
        .row {
            height: 70px;
            display: flex;
            flex-direction: row;
            .number {
                width: 75%;
                display: flex;
                color: #ffffff;
                span {
                    width: calc(100%/3);
                    height: 70px;
                    text-align: center;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    user-select: none;
                    cursor: pointer;
                }
            }
            .symbol {
                width: 25%;
                background-color: #ffffff;
                font-size: 34px;
                span {
                    width: 100%;
                    height: 70px;
                    text-align: center;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    user-select: none;
                    cursor: pointer;
                }
                &.action {
                    background: linear-gradient(60deg, #ff0300, #ffa100);
                    border-radius: 0 0 10px 0;
                    color: #ffffff;
                    box-shadow: 0 25px 60px -10px rgba(255, 10, 0, 0.5);
                }
            }
        }
    }
}
.dull {
    font-size: 14px;
    font-weight: bold;
    color: #4a4a4a;
}

Add javascript code for page

import { Component, OnInit } from '@angular/core';
@Component({
	selector: 'app-calculator1',
	templateUrl: './calculator.page.html',
	styleUrls: ['./calculator.page.scss'],
})
export class CalculatorPage implements OnInit {
	result = "";
	constructor() { }
	ngOnInit() {
	}
	btnClicked(btn) {
		console.log('CalculatorPage::btnClicked = ' + btn);
		if (btn == "C") {
			this.result = "";
		} else if (btn == "=") {
			this.result = eval(this.result);
		} else if (btn == "squareroot") {
			this.result = Math.sqrt(eval(this.result)) + "";
		} else if (btn == "square") {
			this.result = eval("(" + this.result + ") * ( " + this.result + ")");
		} else if (btn == "reciproc") {
			this.result = eval(1 + "/ (" + this.result + ")");
		} else {
			this.result += btn;
		}
	}
}

The final result