Skip to content

Instantly share code, notes, and snippets.

@florentdestremau
Created July 3, 2024 07:30
Show Gist options
  • Save florentdestremau/673361af12190d9acf5f4e6e780d3d1e to your computer and use it in GitHub Desktop.
Save florentdestremau/673361af12190d9acf5f4e6e780d3d1e to your computer and use it in GitHub Desktop.
The list of git alises from Oh My Zsh but ported to bash. You can paste this in your .bashrc or include it from elsewhere
function _omb_prompt_git {
command git "$@"
}
function _omb_prompt_git_status_enabled {
[[ $(_omb_prompt_git config --get-regexp '^(oh-my-zsh|bash-it|oh-my-bash)\.hide-status$' |
awk '$2== "1" {hide_status = 1;} END { print hide_status; }') != "1" ]]
}
# # Note: The same name of a functionis defined in omb-prompt-base. We comment
# # out this function for now.
# function git_prompt_info {
# local ref
# if [[ $(_omb_prompt_git config --get oh-my-bash.hide-status 2>/dev/null) != 1 ]]; then
# ref=$(_omb_prompt_git symbolic-ref HEAD 2> /dev/null) || \
# ref=$(_omb_prompt_git rev-parse --short HEAD 2> /dev/null) || return 0
# echo "$OSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$OSH_THEME_GIT_PROMPT_SUFFIX"
# fi
# }
# Checks if working tree is dirty
function parse_git_dirty {
local STATUS=
local -a FLAGS=('--porcelain')
if [[ $(_omb_prompt_git config --get oh-my-bash.hide-dirty) != 1 ]]; then
if ((${_omb_git_post_1_7_2:=$(git_compare_version "1.7.2")} > 0)); then
FLAGS+=('--ignore-submodules=dirty')
fi
if [[ $DISABLE_UNTRACKED_FILES_DIRTY == "true" ]]; then
FLAGS+=('--untracked-files=no')
fi
STATUS=$(_omb_prompt_git status "${FLAGS[@]}" 2>/dev/null | tail -n1)
fi
if [[ $STATUS ]]; then
echo "$OSH_THEME_GIT_PROMPT_DIRTY"
else
echo "$OSH_THEME_GIT_PROMPT_CLEAN"
fi
}
# Gets the difference between the local and remote branches
function git_remote_status {
local git_remote_origin=$(_omb_prompt_git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)
local remote=${git_remote_origin/refs\/remotes\//}
if [[ $remote ]]; then
local ahead=$(_omb_prompt_git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
local behind=$(_omb_prompt_git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
local git_remote_status git_remote_status_detailed
if ((ahead == 0 && behind == 0)); then
git_remote_status=$OSH_THEME_GIT_PROMPT_EQUAL_REMOTE
elif ((ahead > 0 && behind == 0)); then
git_remote_status=$OSH_THEME_GIT_PROMPT_AHEAD_REMOTE
git_remote_status_detailed=$OSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$OSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))$_omb_prompt_reset_color
elif ((behind > 0 && ahead == 0)); then
git_remote_status=$OSH_THEME_GIT_PROMPT_BEHIND_REMOTE
git_remote_status_detailed=$OSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$OSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))$_omb_prompt_reset_color
elif ((ahead > 0 && behind > 0)); then
git_remote_status=$OSH_THEME_GIT_PROMPT_DIVERGED_REMOTE
git_remote_status_detailed=$OSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$OSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))$_omb_prompt_reset_color$OSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$OSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))$_omb_prompt_reset_color
fi
if [[ $OSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED ]]; then
git_remote_status=$OSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX$remote$git_remote_status_detailed$OSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX
fi
echo "$git_remote_status"
fi
}
# Outputs the name of the current branch
# Usage example: git pull origin $(git_current_branch)
# Using '--quiet' with 'symbolic-ref' will not cause a fatal error (128) if
# it's not a symbolic ref, but in a Git repo.
function git_current_branch {
local ref
ref=$(_omb_prompt_git symbolic-ref --quiet HEAD 2>/dev/null)
local ret=$?
if [[ $ret != 0 ]]; then
[[ $ret == 128 ]] && return # no git repo.
ref=$(_omb_prompt_git rev-parse --short HEAD 2>/dev/null) || return
fi
echo ${ref#refs/heads/}
}
# Gets the number of commits ahead from remote
function git_commits_ahead {
if _omb_prompt_git rev-parse --git-dir &>/dev/null; then
local commits=$(_omb_prompt_git rev-list --count @{upstream}..HEAD)
if ((commits != 0)); then
echo "$OSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$OSH_THEME_GIT_COMMITS_AHEAD_SUFFIX"
fi
fi
}
# Gets the number of commits behind remote
function git_commits_behind {
if _omb_prompt_git rev-parse --git-dir &>/dev/null; then
local commits=$(_omb_prompt_git rev-list --count HEAD..@{upstream})
if ((commits != 0)); then
echo "$OSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$OSH_THEME_GIT_COMMITS_BEHIND_SUFFIX"
fi
fi
}
# Outputs if current branch is ahead of remote
function git_prompt_ahead {
if [[ $(_omb_prompt_git rev-list origin/$(git_current_branch)..HEAD 2>/dev/null) ]]; then
echo "$OSH_THEME_GIT_PROMPT_AHEAD"
fi
}
# Outputs if current branch is behind remote
function git_prompt_behind {
if [[ $(_omb_prompt_git rev-list HEAD..origin/$(git_current_branch) 2>/dev/null) ]]; then
echo "$OSH_THEME_GIT_PROMPT_BEHIND"
fi
}
# Outputs if current branch exists on remote or not
function git_prompt_remote {
if [[ $(_omb_prompt_git show-ref origin/$(git_current_branch) 2>/dev/null) ]]; then
echo "$OSH_THEME_GIT_PROMPT_REMOTE_EXISTS"
else
echo "$OSH_THEME_GIT_PROMPT_REMOTE_MISSING"
fi
}
# Formats prompt string for current git commit short SHA
function git_prompt_short_sha {
local SHA
SHA=$(_omb_prompt_git rev-parse --short HEAD 2>/dev/null) &&
echo "$OSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$OSH_THEME_GIT_PROMPT_SHA_AFTER"
}
# Formats prompt string for current git commit long SHA
function git_prompt_long_sha {
local SHA
SHA=$(_omb_prompt_git rev-parse HEAD 2>/dev/null) &&
echo "$OSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$OSH_THEME_GIT_PROMPT_SHA_AFTER"
}
# Get the status of the working tree
function git_prompt_status {
local INDEX=$(_omb_prompt_git status --porcelain -b 2>/dev/null)
local STATUS=
if command grep -qE '^\?\? ' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_UNTRACKED$STATUS
fi
if command grep -q '^[AM] ' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_ADDED$STATUS
fi
if command grep -qE '^[ A]M |^ T ' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_MODIFIED$STATUS
fi
if command grep -q '^R ' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_RENAMED$STATUS
fi
if command grep -qE '^[ A]D |D ' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_DELETED$STATUS
fi
if _omb_prompt_git rev-parse --verify refs/stash &>/dev/null; then
STATUS=$OSH_THEME_GIT_PROMPT_STASHED$STATUS
fi
if command grep -q '^UU ' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_UNMERGED$STATUS
fi
if command grep -q '^## [^ ]\+ .*ahead' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_AHEAD$STATUS
fi
if command grep -q '^## [^ ]\+ .*behind' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_BEHIND$STATUS
fi
if command grep -q '^## [^ ]\+ .*diverged' <<<"$INDEX"; then
STATUS=$OSH_THEME_GIT_PROMPT_DIVERGED$STATUS
fi
echo "$STATUS"
}
# Compares the provided version of git to the version installed and on path
# Outputs -1, 0, or 1 if the installed version is less than, equal to, or
# greater than the input version, respectively.
function git_compare_version {
local INPUT_GIT_VERSION INSTALLED_GIT_VERSION
_omb_util_split INPUT_GIT_VERSION "$1" '.'
_omb_util_split INSTALLED_GIT_VERSION "$(_omb_prompt_git --version 2>/dev/null)"
_omb_util_split INSTALLED_GIT_VERSION "${INSTALLED_GIT_VERSION[2]}" '.'
local i
for i in {0..2}; do
if ((INSTALLED_GIT_VERSION[i] > INPUT_GIT_VERSION[i])); then
echo 1
return 0
fi
if ((INSTALLED_GIT_VERSION[i] < INPUT_GIT_VERSION[i])); then
echo -1
return 0
fi
done
echo 0
}
# Outputs the name of the current user
# Usage example: $(git_current_user_name)
function git_current_user_name {
_omb_prompt_git config user.name 2>/dev/null
}
# Outputs the email of the current user
# Usage example: $(git_current_user_email)
function git_current_user_email {
_omb_prompt_git config user.email 2>/dev/null
}
#! bash oh-my-bash.module
#
# Functions
#
# The name of the current branch
# Back-compatibility wrapper for when this function was defined here in
# the plugin, before being pulled in to core lib/git.zsh as git_current_branch()
# to fix the core -> git plugin dependency.
function current_branch() {
git_current_branch
}
# The list of remotes
function current_repository() {
if ! $_omb_git_git_cmd rev-parse --is-inside-work-tree &>/dev/null; then
return
fi
echo $($_omb_git_git_cmd remote -v | cut -d':' -f 2)
}
# Warn if the current branch is a WIP
function work_in_progress() {
if $(git log -n 1 2>/dev/null | grep -q -c "\-\-wip\-\-"); then
echo "WIP!!"
fi
}
# Check for develop and similarly named branches
function git_develop_branch() {
command git rev-parse --git-dir &>/dev/null || return
local branch
for branch in dev devel development; do
if command git show-ref -q --verify refs/heads/"$branch"; then
echo "$branch"
return
fi
done
echo develop
}
# Check if main exists and use instead of master
function git_main_branch() {
command git rev-parse --git-dir &>/dev/null || return
local ref
for ref in refs/{heads,remotes/{origin,upstream}}/{main,trunk,mainline,default}; do
if command git show-ref -q --verify "$ref"; then
echo "${ref##*/}"
return
fi
done
echo master
}
#
# Aliases
#
# From Oh-My-Zsh:
# https://github.com/ohmyzsh/ohmyzsh/blob/f36c6db0eac17b022eee87411e6996a5f5fc8457/plugins/git/git.plugin.zsh
#
alias g='command git'
alias ga='command git add'
alias gaa='command git add --all'
alias gapa='command git add --patch'
alias gau='command git add --update'
alias gav='command git add --verbose'
alias gwip='command git add -A; command git rm $(git ls-files --deleted) 2> /dev/null; command git commit --no-verify --no-gpg-sign --message "--wip-- [skip ci]"'
alias gam='command git am'
alias gama='command git am --abort'
alias gamc='command git am --continue'
alias gamscp='command git am --show-current-patch'
alias gams='command git am --skip'
alias gap='command git apply'
alias gapt='command git apply --3way'
alias gbl='command git blame -b -w'
alias gb='command git branch'
alias gbD='command git branch --delete --force'
alias gba='command git branch -a'
alias gbd='command git branch -d'
alias gbda='command git branch --no-color --merged | command grep -vE "^([+*]|\s*($(git_main_branch)|$(git_develop_branch))\s*$)" | command xargs git branch --delete 2>/dev/null'
alias gbg='LANG=C command git branch -vv | grep ": gone\]"'
alias gbgD='LANG=C command git branch --no-color -vv | grep ": gone\]" | awk '"'"'{print $1}'"'"' | command xargs git branch -D'
alias gbgd='LANG=C command git branch --no-color -vv | grep ": gone\]" | awk '"'"'{print $1}'"'"' | command xargs git branch -d'
alias gbm='command git branch --move'
alias gbnm='command git branch --no-merged'
alias gbr='command git branch --remote'
alias gbsc='command git branch --show-current'
alias ggsup='command git branch --set-upstream-to="origin/$(git_current_branch)"'
alias gbs='command git bisect'
alias gbsb='command git bisect bad'
alias gbsg='command git bisect good'
alias gbsn='command git bisect new'
alias gbso='command git bisect old'
alias gbsr='command git bisect reset'
alias gbss='command git bisect start'
alias gcb='command git checkout -b'
alias gcd='command git checkout "$(git_develop_branch)"'
alias gcm='command git checkout "$(git_main_branch)"'
alias gco='command git checkout'
alias gcor='command git checkout --recurse-submodules'
alias gcp='command git cherry-pick'
alias gcpa='command git cherry-pick --abort'
alias gcpc='command git cherry-pick --continue'
alias gcps='command git cherry-pick -s'
alias gcl='command git clone --recursive'
function gccd() {
command git clone --recurse-submodules "$@"
local lastarg=$_
[[ -d $lastarg ]] && cd "$lastarg" && return
lastarg=${lastarg##*/}
cd "${lastarg%.git}"
}
#compdef _git gccd=git-clone
alias gclean='command git clean -fd'
alias gc!='command git commit --verbose --amend'
alias gc='command git commit --verbose'
alias gca!='command git commit --verbose --all --amend'
alias gca='command git commit --verbose --all'
alias gcam='command git commit --all --message'
alias gcan!='command git commit --verbose --all --no-edit --amend'
alias gcans!='command git commit --verbose --all --signoff --no-edit --amend'
alias gcas='command git commit --all --signoff'
alias gcasm='command git commit --all --signoff --message'
alias gcmsg='command git commit --message'
alias gcn!='command git commit --verbose --no-edit --amend'
alias gcs='command git commit --gpg-sign'
alias gcsm='command git commit --signoff --message'
alias gcss='command git commit --gpg-sign --signoff'
alias gcssm='command git commit --gpg-sign --signoff --message'
alias gcf='command git config --list'
alias gdct='command git describe --tags `git rev-list --tags --max-count=1`'
alias gd='command git diff'
alias gdca='command git diff --cached'
alias gdcw='command git diff --cached --word-diff'
alias gds='command git diff --staged'
alias gdw='command git diff --word-diff'
alias gdup='command git diff @{upstream}'
function gdnolock() {
command git diff "$@" ":(exclude)package-lock.json" ":(exclude)*.lock"
}
#compdef _git gdnolock=git-diff
function gdv {
command git diff -w "$@" | view -
}
#compdef _git gdv=git-diff
alias gdt='command git diff-tree --no-commit-id --name-only -r'
alias gdtool='command git difftool -d'
alias gf='command git fetch'
alias gfa='command git fetch --all --prune'
alias gfo='command git fetch origin'
# jobs=<n> was added in git 2.8
# alias gfa='git fetch --all --prune --jobs=10' \
alias gg='command git gui citool'
alias gga='command git gui citool --amend'
alias ghh='command git help'
alias glg='command git log --stat'
alias glgg='command git log --graph'
alias glgga='command git log --graph --decorate --all'
alias glgm='command git log --graph --max-count=10'
alias glgp='command git log --stat -p'
alias glo='command git log --oneline --decorate'
alias glod='command git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset"'
alias glods='command git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ad) %C(bold blue)<%an>%Creset" --date=short'
alias glog='command git log --oneline --decorate --graph'
alias gloga='command git log --oneline --decorate --graph --all'
alias glol='command git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset"'
alias glola='command git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --all'
alias glols='command git log --graph --pretty="%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%ar) %C(bold blue)<%an>%Creset" --stat'
# Pretty log messages
function _git_log_prettily() {
if [[ $1 ]]; then
command git log --pretty="$1"
fi
}
alias glp='_git_log_prettily'
#compdef _git glp=git-log
alias gignored='command git ls-files -v | grep "^[[:lower:]]"'
alias gfg='command git ls-files | grep'
alias gm='command git merge'
alias gma='command git merge --abort'
alias gmom='command git merge "origin/$(git_main_branch)"'
alias gms='command git merge --squash'
alias gmum='command git merge "upstream/$(git_main_branch)"'
alias gmt='command git mergetool --no-prompt' # deprecate?
alias gmtvim='command git mergetool --no-prompt --tool=vimdiff' # deprecate?
alias gmtl='command git mergetool --no-prompt'
alias gmtlvim='command git mergetool --no-prompt --tool=vimdiff'
alias ggpull='command git pull origin "$(git_current_branch)"'
alias ggpur='ggu'
alias gl='command git pull'
alias gluc='command git pull upstream "$(git_current_branch)"'
alias glum='command git pull upstream "$(git_main_branch)"'
alias gpr='command git pull --rebase'
alias gup='command git pull --rebase'
alias gupa='command git pull --rebase --autostash'
alias gupav='command git pull --rebase --autostash --verbose'
alias gupom='command git pull --rebase origin "$(git_main_branch)"'
alias gupomi='command git pull --rebase=interactive origin "$(git_main_branch)"'
alias gupv='command git pull --rebase --verbose'
function ggl {
if (($# != 0 && $# != 1)); then
command git pull origin "$*"
else
local b=
(($# == 0)) && b=$(git_current_branch)
command git pull origin "${b:-$1}"
fi
}
function ggu {
local b=
(($# != 1)) && b=$(git_current_branch)
command git pull --rebase origin "${b:-$1}"
}
#compdef _git ggl=git-checkout
#compdef _git ggpull=git-checkout
#compdef _git ggpur=git-checkout
#compdef _git ggu=git-checkout
alias ggpush='command git push origin "$(git_current_branch)"'
alias gp='command git push'
alias gpd='command git push --dry-run'
alias gpf!='command git push --force'
alias gpf='command git push --force-with-lease'
alias gpoat='command git push origin --all && command git push origin --tags'
alias gpod='command git push origin --delete'
alias gpsup='command git push --set-upstream origin "$(git_current_branch)"'
alias gpsupf='command git push --set-upstream origin "$(git_current_branch)" --force-with-lease'
alias gpu='command git push upstream'
alias gpv='command git push --verbose'
#is-at-least 2.30 "$git_version" && alias gpf='git push --force-with-lease --force-if-includes'
#is-at-least 2.30 "$git_version" && alias gpsupf='git push --set-upstream origin "$(git_current_branch)" --force-with-lease --force-if-includes'
function ggf {
(($# != 1)) && local b=$(git_current_branch)
command git push --force origin "${b:=$1}"
}
function ggfl {
(($# != 1)) && local b=$(git_current_branch)
command git push --force-with-lease origin "${b:=$1}"
}
function ggp {
if (($# != 0 && $# != 1)); then
command git push origin "$*"
else
(($# == 0)) && local b=$(git_current_branch)
command git push origin "${b:=$1}"
fi
}
function ggpnp {
if (($# == 0)); then
ggl && ggp
else
ggl "$*" && ggp "$*"
fi
}
#compdef _git ggf=git-checkout
#compdef _git ggfl=git-checkout
#compdef _git ggp=git-checkout
#compdef _git ggpnp=git-checkout
#compdef _git ggpush=git-checkout
#compdef _git gpoat=git-push
alias grb='command git rebase'
alias grba='command git rebase --abort'
alias grbc='command git rebase --continue'
alias grbi='command git rebase --interactive'
alias grbo='command git rebase --onto'
alias grbs='command git rebase --skip'
alias grbd='command git rebase "$(git_develop_branch)"'
alias grbm='command git rebase "$(git_main_branch)"'
alias grbom='command git rebase "origin/$(git_main_branch)"'
alias gr='command git remote'
alias gra='command git remote add'
alias grmv='command git remote rename'
alias grrm='command git remote remove'
alias grset='command git remote set-url'
alias grup='command git remote update'
alias grv='command git remote --verbose'
alias gpristine='command git reset --hard && command git clean --force -dfx'
alias grh='command git reset'
alias grhh='command git reset --hard'
alias grhk='command git reset --keep'
alias grhs='command git reset --soft'
alias groh='command git reset "origin/$(git_current_branch)" --hard'
alias grt='cd $(command git rev-parse --show-toplevel || echo ".")'
alias gru='command git reset --'
alias grs='command git restore'
alias grss='command git restore --source'
alias grst='command git restore --staged'
alias gunwip='command git rev-list --max-count=1 --format="%s" HEAD | grep -q "\--wip--" && command git reset HEAD~1'
alias grev='command git revert'
alias grm='command git rm'
alias grmc='command git rm --cached'
alias gcount='command git shortlog --summary --numbered'
#compdef _git gcount complete -F _git gcount
alias gsh='command git show'
alias gsps='command git show --pretty=short --show-signature'
alias gsta='command git stash save'
alias gstaa='command git stash apply'
alias gstall='command git stash --all'
alias gstc='command git stash clear'
alias gstd='command git stash drop'
alias gstl='command git stash list'
alias gstp='command git stash pop'
alias gsts='command git stash show'
alias gstu='gsta --include-untracked'
#is-at-least 2.13 "$git_version" && alias gsta='command git stash push'
alias gsb='command git status --short --branch'
alias gss='command git status --short'
alias gst='command git status'
alias gsi='command git submodule init'
alias gsu='command git submodule update'
alias git-svn-dcommit-push='command git svn dcommit && command git push github "$(git_main_branch):svntrunk"'
alias gsd='command git svn dcommit'
alias gsr='command git svn rebase'
#compdef _git git-svn-dcommit-push=git
alias gsw='command git switch'
alias gswc='command git switch --create'
alias gswd='command git switch "$(git_develop_branch)"'
alias gswm='command git switch "$(git_main_branch)"'
alias gta='command git tag --annotate'
alias gts='command git tag --sign'
alias gtv='command git tag | sort -V'
function gtl {
command git tag --sort=-v:refname -n --list "$1*"
}
#compdef _git gtl=git-tag
alias gignore='command git update-index --assume-unchanged'
alias gunignore='command git update-index --no-assume-unchanged'
alias gwch='command git whatchanged -p --abbrev-commit --pretty=medium'
alias gwt='command git worktree'
alias gwta='command git worktree add'
alias gwtls='command git worktree list'
alias gwtmv='command git worktree move'
alias gwtrm='command git worktree remove'
alias gk='\gitk --all --branches'
alias gke='\gitk --all $(git log --walk-reflogs --pretty=%h)'
# alias gk='\gitk --all --branches &!'
# alias gke='\gitk --all $(git log --walk-reflogs --pretty=%h) &!'
#compdef _git gk='command gitk'
#compdef _git gke='command gitk'
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment