Files
fortunecookie/git-helper.sh
T
2026-06-01 17:16:02 +02:00

679 lines
19 KiB
Bash
Executable File

#!/bin/bash
#
# Git-Helper für Ubuntu Touch Entwicklung
# Version: 1.7
# Autor: darklithium <dev@darklithium.de>
#
# Zweck: Narrensicheres Git für Entwickler
# - Einfache Befehle für häufige Git-Operationen
# - Automatische Branch-Naming
# - Konsistente Workflows
#
# Verwendung:
# ./git-helper.sh <befehl> [argumente]
#
# Beispiele:
# ./git-helper.sh status
# ./git-helper.sh new-feature login-system
# ./git-helper.sh merge-stable
# --- KONFIGURATION ---
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [[ -z "$REPO_ROOT" ]]; then
echo "❌ Nicht in einem Git-Repository!"
echo " → cd /pfad/zu/deinem/git/repo"
exit 1
fi
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null | sed 's/refs\/heads\///')
MAINTAINER="darklithium <dev@darklithium.de>"
# Farben
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# --- FUNKTIONEN ---
# Hilfstext anzeigen
show_help() {
cat << EOF
📖 Git-Helper v1.7 - Hilfstext
Verfügbare Befehle:
📊 STATUS & INFO
status Zeigt Git-Status an
branches Liste alle Branches
log Zeigt Commit-Historie
diff Zeigt unstaged Änderungen
diff-staged Zeigt staged Änderungen
🌿 BRANCHES
new-feature <name> Erstellt Feature-Branch (Basis: testing)
new-bugfix <name> Erstellt Bugfix-Branch (Basis: testing)
new-hotfix <name> Erstellt Hotfix-Branch (Basis: stable)
switch <branch> Wechselt zu Branch
delete <branch> Löscht Branch (lokal)
🔄 MERGE & REBASE
merge-stable Merged testing → stable
merge-testing Merged feature/* → testing
rebase-testing Rebase aktuellen Branch auf testing
📤 PUSH & PULL
push Pushed aktuellen Branch
pull Pullt Änderungen
push-all Pushed alle Branches
fetch Fetched alle Remote-Branches
🏷️ TAGS
tag <version> Erstellt Tag (z. B. v1.0.0)
tag-push <version> Pushed Tag zum Remote
tags Liste alle Tags
📝 COMMITS
commit <msg> Erstellt Commit mit Message
amend Ändert letzten Commit
revert <commit> Revertet einen Commit
🧹 AUFRÄUMEN
cleanup Löscht gemergte Branches
cleanup-all Löscht alle lokalen Branches außer stable/testing
📋 REVIEW
review Zeigt Commits zur Review
review-last Zeigt letzten Commit detailliert
❓ HILFE
help Zeigt diesen Hilfstext
version Zeigt Version
Beispiele:
./git-helper.sh new-feature login-system
./git-helper.sh switch testing
./git-helper.sh merge-stable
./git-helper.sh push
EOF
}
# Zeigt aktuellen Status
cmd_status() {
echo ""
echo -e "${BLUE}=== Git-Status ===${NC}"
echo ""
echo -e "${YELLOW}Repository:${NC} $REPO_ROOT"
echo -e "${YELLOW}Aktueller Branch:${NC} $CURRENT_BRANCH"
echo ""
# Branch-Status
if [[ "$CURRENT_BRANCH" == "stable" || "$CURRENT_BRANCH" == "testing" ]]; then
echo -e "${GREEN}✅ Haupt-Branch${NC}"
elif [[ "$CURRENT_BRANCH" =~ ^feature/ ]]; then
echo -e "${BLUE}📌 Feature-Branch${NC}"
elif [[ "$CURRENT_BRANCH" =~ ^bugfix/ ]]; then
echo -e "${RED}🐛 Bugfix-Branch${NC}"
elif [[ "$CURRENT_BRANCH" =~ ^hotfix/ ]]; then
echo -e "${RED}🚨 Hotfix-Branch${NC}"
else
echo -e "${YELLOW}⚠️ Unbekannter Branch-Typ${NC}"
fi
echo ""
echo -e "${YELLOW}Änderungen:${NC}"
git status --short
echo ""
echo -e "${YELLOW}Remote-Status:${NC}"
git remote -v
echo ""
}
# Liste alle Branches
cmd_branches() {
echo ""
echo -e "${BLUE}=== Alle Branches ===${NC}"
echo ""
echo -e "${GREEN}🟢 Haupt-Branches:${NC}"
git branch | grep -E '^\*?\s*(stable|testing|main|master)$' | sed 's/^[ *]//'
echo ""
echo -e "${BLUE}📌 Feature-Branches:${NC}"
git branch | grep -E '^\*?\s*feature/' | sed 's/^[ *]//'
echo ""
echo -e "${RED}🐛 Bugfix-Branches:${NC}"
git branch | grep -E '^\*?\s*bugfix/' | sed 's/^[ *]//'
echo ""
echo -e "${RED}🚨 Hotfix-Branches:${NC}"
git branch | grep -E '^\*?\s*hotfix/' | sed 's/^[ *]//'
}
# Zeigt Commit-Historie
cmd_log() {
echo ""
echo -e "${BLUE}=== Commit-Historie ===${NC}"
echo ""
git log --oneline --graph --all -20
echo ""
}
# Zeigt unstaged Änderungen
cmd_diff() {
echo ""
echo -e "${BLUE}=== Unstaged Änderungen ===${NC}"
echo ""
git diff
}
# Zeigt staged Änderungen
cmd_diff_staged() {
echo ""
echo -e "${BLUE}=== Staged Änderungen ===${NC}"
echo ""
git diff --cached
}
# Erstellt Feature-Branch
cmd_new_feature() {
local branch_name="feature/$1"
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
echo " → ./git-helper.sh new-feature <name>"
exit 1
fi
# Prüfe ob Branch schon existiert
if git show-ref --verify --quiet refs/heads/"$branch_name"; then
echo -e "${RED}❌ Branch '$branch_name' existiert bereits!${NC}"
exit 1
fi
# Basis-Branch prüfen (sollte testing sein)
if git show-ref --verify --quiet refs/heads/testing; then
BASE_BRANCH="testing"
elif git show-ref --verify --quiet refs/heads/stable; then
BASE_BRANCH="stable"
echo -e "${YELLOW}⚠️ testing-Branch nicht gefunden, verwende stable${NC}"
else
echo -e "${RED}❌ Basis-Branch (testing oder stable) nicht gefunden!${NC}"
exit 1
fi
# Branch erstellen und wechseln
git checkout -b "$branch_name" "$BASE_BRANCH"
echo -e "${GREEN}✅ Feature-Branch '$branch_name' erstellt (Basis: $BASE_BRANCH)${NC}"
echo " → git push --set-upstream origin $branch_name"
}
# Erstellt Bugfix-Branch
cmd_new_bugfix() {
local branch_name="bugfix/$1"
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
echo " → ./git-helper.sh new-bugfix <name>"
exit 1
fi
# Prüfe ob Branch schon existiert
if git show-ref --verify --quiet refs/heads/"$branch_name"; then
echo -e "${RED}❌ Branch '$branch_name' existiert bereits!${NC}"
exit 1
fi
# Basis-Branch prüfen
if git show-ref --verify --quiet refs/heads/testing; then
BASE_BRANCH="testing"
elif git show-ref --verify --quiet refs/heads/stable; then
BASE_BRANCH="stable"
echo -e "${YELLOW}⚠️ testing-Branch nicht gefunden, verwende stable${NC}"
else
echo -e "${RED}❌ Basis-Branch (testing oder stable) nicht gefunden!${NC}"
exit 1
fi
git checkout -b "$branch_name" "$BASE_BRANCH"
echo -e "${GREEN}✅ Bugfix-Branch '$branch_name' erstellt (Basis: $BASE_BRANCH)${NC}"
echo " → git push --set-upstream origin $branch_name"
}
# Erstellt Hotfix-Branch
cmd_new_hotfix() {
local branch_name="hotfix/$1"
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
echo " → ./git-helper.sh new-hotfix <name>"
exit 1
fi
# Prüfe ob Branch schon existiert
if git show-ref --verify --quiet refs/heads/"$branch_name"; then
echo -e "${RED}❌ Branch '$branch_name' existiert bereits!${NC}"
exit 1
fi
# Hotfix muss von stable kommen
if ! git show-ref --verify --quiet refs/heads/stable; then
echo -e "${RED}❌ stable-Branch nicht gefunden!${NC}"
echo " → Hotfix-Branches müssen von stable ausgehen"
exit 1
fi
git checkout -b "$branch_name" stable
echo -e "${GREEN}✅ Hotfix-Branch '$branch_name' erstellt (Basis: stable)${NC}"
echo " → git push --set-upstream origin $branch_name"
}
# Wechselt Branch
cmd_switch() {
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
echo " → ./git-helper.sh switch <branch>"
exit 1
fi
# Branch-Namen validieren
case "$1" in
stable|testing|feature/*|bugfix/*|hotfix/*|release/*)
git checkout "$1"
echo -e "${GREEN}✅ Zu Branch '$1' gewechselt${NC}"
;;
*)
echo -e "${RED}❌ Ungültiger Branch-Name: '$1'${NC}"
echo " → Erlaubt: stable, testing, feature/*, bugfix/*, hotfix/*"
exit 1
;;
esac
}
# Löscht Branch
cmd_delete() {
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlender Branch-Name!${NC}"
echo " → ./git-helper.sh delete <branch>"
exit 1
fi
# Nicht stable oder testing löschen
if [[ "$1" == "stable" || "$1" == "testing" ]]; then
echo -e "${RED}❌ Cannot delete main branches (stable/testing)!${NC}"
exit 1
fi
# Prüfe ob Branch existiert
if ! git show-ref --verify --quiet refs/heads/"$1"; then
echo -e "${RED}❌ Branch '$1' existiert nicht!${NC}"
exit 1
fi
# Prüfe ob Branch aktuell aktiv ist
if [[ "$1" == "$CURRENT_BRANCH" ]]; then
echo -e "${RED}❌ Kann aktiven Branch nicht löschen!${NC}"
echo " → Wechsle zuerst zu einem anderen Branch"
exit 1
fi
git branch -D "$1"
echo -e "${GREEN}✅ Branch '$1' gelöscht (lokal)${NC}"
}
# Merged testing → stable
cmd_merge_stable() {
# Prüfe ob auf stable Branch
if [[ "$CURRENT_BRANCH" != "stable" ]]; then
echo -e "${RED}❌ Nicht auf stable-Branch!${NC}"
echo " → git checkout stable"
exit 1
fi
# Prüfe ob testing existiert
if ! git show-ref --verify --quiet refs/heads/testing; then
echo -e "${RED}❌ testing-Branch existiert nicht!${NC}"
exit 1
fi
echo -e "${YELLOW}🔍 Prüfe ob testing in stable gemerged ist...${NC}"
if git merge --no-commit --no-ff testing 2>/dev/null; then
echo -e "${GREEN}✅ testing kann in stable gemerged werden${NC}"
git merge --no-ff testing -m "merge: testing → stable"
echo ""
echo -e "${GREEN}✅ testing erfolgreich in stable gemerged!${NC}"
echo " → git push origin stable"
echo " → git push origin testing"
else
echo -e "${RED}❌ Merge-Konflikte!${NC}"
echo " → Konflikte manuell lösen und dann:"
echo " → git commit"
echo " → git merge --continue"
exit 1
fi
}
# Merged feature/* → testing
cmd_merge_testing() {
# Prüfe ob auf testing Branch
if [[ "$CURRENT_BRANCH" != "testing" ]]; then
echo -e "${RED}❌ Nicht auf testing-Branch!${NC}"
echo " → git checkout testing"
exit 1
fi
# Zeige alle Feature-Branches
echo -e "${YELLOW}Verfügbare Feature-Branches:${NC}"
git branch | grep -E '^\s*feature/' | sed 's/^[ *]//' | sed 's/feature\///'
echo ""
# Branch-Namen abfragen
read -p "Welchen Feature-Branch möchtest du mergen? (Name ohne 'feature/')? " branch_name
FULL_BRANCH="feature/$branch_name"
# Prüfe ob Branch existiert
if ! git show-ref --verify --quiet refs/heads/"$FULL_BRANCH"; then
echo -e "${RED}❌ Branch '$FULL_BRANCH' existiert nicht!${NC}"
exit 1
fi
echo -e "${YELLOW}🔍 Prüfe ob $FULL_BRANCH in testing gemerged ist...${NC}"
if git merge --no-commit --no-ff "$FULL_BRANCH" 2>/dev/null; then
echo -e "${GREEN}$FULL_BRANCH kann in testing gemerged werden${NC}"
git merge --no-ff "$FULL_BRANCH" -m "merge: $FULL_BRANCH → testing"
echo ""
echo -e "${GREEN}$FULL_BRANCH erfolgreich in testing gemerged!${NC}"
echo " → git push origin testing"
else
echo -e "${RED}❌ Merge-Konflikte!${NC}"
echo " → Konflikte manuell lösen und dann:"
echo " → git commit"
echo " → git merge --continue"
exit 1
fi
}
# Rebase auf testing
cmd_rebase_testing() {
if ! git show-ref --verify --quiet refs/heads/testing; then
echo -e "${RED}❌ testing-Branch existiert nicht!${NC}"
exit 1
fi
echo -e "${YELLOW}🔍 Rebase $CURRENT_BRANCH auf testing...${NC}"
if git rebase testing; then
echo -e "${GREEN}$CURRENT_BRANCH auf testing gerebased!${NC}"
echo " → git push --force-with-lease"
else
echo -e "${RED}❌ Rebase-Konflikte!${NC}"
echo " → Konflikte lösen mit:"
echo " → git rebase --continue (wenn gelöst)"
echo " → git rebase --abort (zum Abbrechen)"
exit 1
fi
}
# Push
cmd_push() {
if [[ -z "$1" ]]; then
# Push aktuellen Branch
git push
echo -e "${GREEN}$CURRENT_BRANCH gepusht${NC}"
else
git push origin "$1"
echo -e "${GREEN}✅ Branch '$1' gepusht${NC}"
fi
}
# Pull
cmd_pull() {
git pull
echo -e "${GREEN}✅ Änderungen gepullt${NC}"
}
# Push alle Branches
cmd_push_all() {
git push --all
echo -e "${GREEN}✅ Alle Branches gepusht${NC}"
}
# Fetch
cmd_fetch() {
git fetch --all
echo -e "${GREEN}✅ Alle Remote-Branches gefetched${NC}"
}
# Erstellt Tag
cmd_tag() {
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlende Versionsnummer!${NC}"
echo " → ./git-helper.sh tag v1.0.0"
exit 1
fi
# Prüfe Format (sollte wie v1.0.0 aussehen)
if ! [[ "$1" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo -e "${YELLOW}⚠️ Tag-Format sollte vMAJOR.MINOR.PATCH sein (z. B. v1.0.0)${NC}"
read -p "Fortfahren mit '$1'? (j/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[JjYy]$ ]]; then
exit 1
fi
fi
git tag -a "$1" -m "Release $1"
echo -e "${GREEN}✅ Tag '$1' erstellt${NC}"
echo " → git-helper.sh tag-push $1"
}
# Pushed Tag
cmd_tag_push() {
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlender Tag-Name!${NC}"
echo " → ./git-helper.sh tag-push v1.0.0"
exit 1
fi
git push origin "$1"
echo -e "${GREEN}✅ Tag '$1' gepusht${NC}"
}
# Liste alle Tags
cmd_tags() {
echo ""
echo -e "${BLUE}=== Alle Tags ===${NC}"
echo ""
git tag -l
}
# Erstellt Commit
cmd_commit() {
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlende Commit-Message!${NC}"
echo " → ./git-helper.sh commit 'feat: neue Funktion'"
exit 1
fi
# Prüfe Format (sollte Typ: Beschreibung sein)
if ! [[ "$1" =~ ^[a-z]+:\ .+ ]]; then
echo -e "${YELLOW}⚠️ Commit-Message sollte Format <Typ>: <Beschreibung> haben${NC}"
echo " Beispiel: feat: neue Funktion"
echo ""
read -p "Fortfahren mit '$1'? (j/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[JjYy]$ ]]; then
exit 1
fi
fi
git commit -m "$1"
echo -e "${GREEN}✅ Commit erstellt: $1${NC}"
}
# Ändert letzten Commit
cmd_amend() {
if [[ -z "$1" ]]; then
git commit --amend --no-edit
echo -e "${GREEN}✅ Letzter Commit geändert (gleiche Message)${NC}"
else
git commit --amend -m "$1"
echo -e "${GREEN}✅ Letzter Commit geändert: $1${NC}"
fi
}
# Revertet Commit
cmd_revert() {
if [[ -z "$1" ]]; then
echo -e "${RED}❌ Fehlende Commit-ID!${NC}"
echo " → ./git-helper.sh revert <commit-hash>"
exit 1
fi
git revert "$1"
echo -e "${GREEN}✅ Commit $1 revertet${NC}"
}
# Löscht gemergte Branches
cmd_cleanup() {
echo -e "${YELLOW}🔍 Suche gemergte Branches...${NC}"
# Alle Branches außer stable und testing
MERGED_BRANCHES=$(git branch --merged stable | grep -v -E '^\*?\s*(stable|testing|main|master)$' | sed 's/^[ *]//' | sed 's/^[[:space:]]*//')
if [[ -z "$MERGED_BRANCHES" ]]; then
echo -e "${GREEN}✅ Keine gemergten Branches zum Löschen gefunden${NC}"
exit 0
fi
echo -e "${YELLOW}Gemergte Branches:${NC}"
echo "$MERGED_BRANCHES"
echo ""
read -p "Alle gemergten Branches löschen? (j/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[JjYy]$ ]]; then
for branch in $MERGED_BRANCHES; do
git branch -D "$branch"
echo -e "${GREEN}✅ Gelöscht: $branch${NC}"
done
echo -e "${GREEN}✅ Alle gemergten Branches gelöscht${NC}"
else
echo -e "${YELLOW}❌ Abgebrochen${NC}"
fi
}
# Löscht alle lokalen Branches außer stable/testing
cmd_cleanup_all() {
echo -e "${RED}⚠️ WARNING: Dies löscht ALLE lokalen Branches außer stable und testing!${NC}"
echo ""
read -p "Fortfahren? (j/n): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[JjYy]$ ]]; then
echo -e "${YELLOW}❌ Abgebrochen${NC}"
exit 0
fi
# Alle Branches außer stable und testing
ALL_BRANCHES=$(git branch | grep -v -E '^\*?\s*(stable|testing|main|master)$' | sed 's/^[ *]//' | sed 's/^[[:space:]]*//')
if [[ -z "$ALL_BRANCHES" ]]; then
echo -e "${GREEN}✅ Keine zusätzlichen Branches gefunden${NC}"
exit 0
fi
for branch in $ALL_BRANCHES; do
git branch -D "$branch"
echo -e "${GREEN}✅ Gelöscht: $branch${NC}"
done
echo -e "${GREEN}✅ Alle lokalen Branches (außer stable/testing) gelöscht${NC}"
}
# Zeigt Commits zur Review
cmd_review() {
echo ""
echo -e "${BLUE}=== Commits zur Review (nicht gepusht) ===${NC}"
echo ""
git log --oneline origin/$CURRENT_BRANCH..$CURRENT_BRANCH
echo ""
if [[ $? -eq 0 && -n "$(git log --oneline origin/$CURRENT_BRANCH..$CURRENT_BRANCH 2>/dev/null)" ]]; then
echo -e "${YELLOW}📝 Tipp: Nutze diese Commits für Code-Review${NC}"
fi
}
# Zeigt letzten Commit detailliert
cmd_review_last() {
echo ""
echo -e "${BLUE}=== Letzter Commit ===${NC}"
echo ""
git show HEAD --stat
echo ""
}
# Zeigt Version
cmd_version() {
echo "Git-Helper v1.7"
echo "Framework: START-UT-DEV 1.7"
echo "Maintainer: darklithium <dev@darklithium.de>"
echo "Stand: 30.05.2026"
}
# --- HAUPTPROGRAMM ---
# Keine Argumente → Hilfe anzeigen
if [[ $# -eq 0 ]]; then
show_help
exit 0
fi
# Command Dispatch
COMMAND="$1"
shift
case "$COMMAND" in
status) cmd_status ;;
branches) cmd_branches ;;
log) cmd_log ;;
diff) cmd_diff ;;
diff-staged) cmd_diff_staged ;;
new-feature) cmd_new_feature "$1" ;;
new-bugfix) cmd_new_bugfix "$1" ;;
new-hotfix) cmd_new_hotfix "$1" ;;
switch) cmd_switch "$1" ;;
delete) cmd_delete "$1" ;;
merge-stable) cmd_merge_stable ;;
merge-testing) cmd_merge_testing ;;
rebase-testing) cmd_rebase_testing ;;
push) cmd_push "$1" ;;
pull) cmd_pull ;;
push-all) cmd_push_all ;;
fetch) cmd_fetch ;;
tag) cmd_tag "$1" ;;
tag-push) cmd_tag_push "$1" ;;
tags) cmd_tags ;;
commit) cmd_commit "$*" ;;
amend) cmd_amend "$*" ;;
revert) cmd_revert "$1" ;;
cleanup) cmd_cleanup ;;
cleanup-all) cmd_cleanup_all ;;
review) cmd_review ;;
review-last) cmd_review_last ;;
help) show_help ;;
version) cmd_version ;;
*)
echo -e "${RED}❌ Unbekannter Befehl: $COMMAND${NC}"
echo ""
show_help
exit 1
;;
esac