Contents:
Commands #
Cleanup a local repository of all untracked files:
git clean -dfx
Throw away all uncommitted changes:
git reset --hard HEAD
Large files support #
Resources:
Installation:
brew install git-lfs
In the git repository:
git lfs install
To add file extensions to track via “lfs”:
git lfs track "*.psd"
git-sync #
Mirroring #
For the purposes of working in a Docker container with a macOS host:
# macOS: initial corporate clone
git clone --mirror <corporate-origin-url> /path/to/project.git
# macOS: allow branch-specific pushes
git -C /path/to/project.git config remote.origin.mirror false
# Docker: clone from the mounted macOS bare repo
git clone --no-local /git/project.git /workspace/project
cd /workspace/project
# Docker -> macOS bare repo
git push origin <branch>
# macOS bare repo -> corporate origin
git-up /path/to/project.git <branch>
# corporate origin -> macOS bare repo
git-down /path/to/project.git <branch>
# macOS bare repo -> Docker
git pull origin <branch>
# If git-down reports divergence
git fetch origin \
refs/remotes/origin/<branch>:refs/remotes/corporate/<branch>
git merge corporate/<branch>
# or
git rebase corporate/<branch>
# Resolve, then
git add <files>
git commit
# or, for rebase
git rebase --continue
# Publish resolved branch
git push origin <branch>
git-up /path/to/project.git <branch>
~/bin/git-up:
#!/usr/bin/env bash
set -uo pipefail
usage() {
echo "Usage: $(basename "$0") <repo.git> <branch>" >&2
exit 2
}
die() {
echo "ERROR: $*" >&2
exit 1
}
[[ $# -eq 2 ]] || usage
repo="$1"
branch="$2"
ref="refs/heads/$branch"
command -v git >/dev/null 2>&1 ||
die "git is not installed or not in PATH"
[[ -d "$repo" ]] ||
die "Repository does not exist: $repo"
git -C "$repo" rev-parse --git-dir >/dev/null 2>&1 ||
die "Not a Git repository: $repo"
[[ "$(git -C "$repo" rev-parse --is-bare-repository)" == "true" ]] ||
die "Expected a bare Git repository: $repo"
git check-ref-format --branch "$branch" >/dev/null 2>&1 ||
die "Invalid branch name: $branch"
git -C "$repo" remote get-url origin >/dev/null 2>&1 ||
die "Remote 'origin' is not configured"
git -C "$repo" show-ref --verify --quiet "$ref" ||
die "Local branch does not exist: $branch"
echo "Pushing '$branch' to origin..."
if ! git -C "$repo" \
-c remote.origin.mirror=false \
push origin "$ref:$ref"
then
cat >&2 <<EOF
ERROR: Push failed.
Possible causes:
- origin contains commits not present locally
- authentication/credentials failed
- origin is unreachable
- the branch is protected
No local refs were modified.
EOF
exit 1
fi
echo "Successfully pushed '$branch'."
~/bin/git-down:
#!/usr/bin/env bash
set -uo pipefail
usage() {
echo "Usage: $(basename "$0") <repo.git> <branch>" >&2
exit 2
}
die() {
echo "ERROR: $*" >&2
exit 1
}
[[ $# -eq 2 ]] || usage
repo="$1"
branch="$2"
local_ref="refs/heads/$branch"
origin_ref="refs/remotes/origin/$branch"
remote_ref="refs/heads/$branch"
command -v git >/dev/null 2>&1 ||
die "git is not installed or not in PATH"
[[ -d "$repo" ]] ||
die "Repository does not exist: $repo"
git -C "$repo" rev-parse --git-dir >/dev/null 2>&1 ||
die "Not a Git repository: $repo"
[[ "$(git -C "$repo" rev-parse --is-bare-repository)" == "true" ]] ||
die "Expected a bare Git repository: $repo"
git check-ref-format --branch "$branch" >/dev/null 2>&1 ||
die "Invalid branch name: $branch"
git -C "$repo" remote get-url origin >/dev/null 2>&1 ||
die "Remote 'origin' is not configured"
echo "Fetching '$branch' from origin..."
if ! git -C "$repo" \
fetch origin "$remote_ref:$origin_ref"
then
die "Could not fetch '$branch' from origin"
fi
origin_commit="$(git -C "$repo" rev-parse "$origin_ref")" ||
die "Could not resolve fetched origin branch"
#
# Branch doesn't exist locally yet.
#
if ! git -C "$repo" show-ref --verify --quiet "$local_ref"; then
git -C "$repo" update-ref "$local_ref" "$origin_commit" ||
die "Could not create local branch '$branch'"
echo "Created local '$branch'."
exit 0
fi
local_commit="$(git -C "$repo" rev-parse "$local_ref")" ||
die "Could not resolve local branch '$branch'"
#
# Already identical.
#
if [[ "$local_commit" == "$origin_commit" ]]; then
echo "'$branch' is already up to date."
exit 0
fi
#
# Local is behind origin: safe fast-forward.
#
if git -C "$repo" merge-base --is-ancestor \
"$local_commit" "$origin_commit"
then
git -C "$repo" update-ref \
"$local_ref" \
"$origin_commit" \
"$local_commit" ||
die "Could not fast-forward '$branch'"
echo "Fast-forwarded '$branch'."
exit 0
fi
#
# Local is ahead: nothing to pull.
#
if git -C "$repo" merge-base --is-ancestor \
"$origin_commit" "$local_commit"
then
echo "Local '$branch' is ahead of origin; nothing to pull."
exit 0
fi
#
# Diverged.
#
cat >&2 <<EOF
ERROR: '$branch' has diverged from origin.
Local:
$local_commit
Origin:
$origin_commit
The local branch was NOT modified.
The origin version is available as:
$origin_ref
Resolve the divergence in your Docker working clone.
EOF
exit 1