GIT🔗
Hard reset local to be like remote🔗
git fetch origin
git reset --hard origin/master
# If you want to keep the current changes, just in case.
git commit -a -m "Just in case"
git branch just-in-case
Delete remote and local branches🔗
Delete local branch:
git branch -d <branchname>
# Example
git branch -d branch_to_delete
Delete remote branch:
git push -d <remote_name> <branchname>
# Example
git push -d origin branch_to_delete
Get the very first commit🔗
If you have git 1.7.4.2 or newer, you can use the --max-parents option:
git rev-list --max-parents=0 HEAD
Otherwise, you can get list of all parentless (root) commits accessible from current branch using:
git rev-list --parents HEAD | egrep "^[a-f0-9]{40}$"
Get the latest tags🔗
From a locally cloned project🔗
To get the most recent tag (example output afterwards):
git describe --tags --abbrev=0 # 0.1.0-dev
To get the most recent tag, with the number of additional commits on top of the tagged object & more:
git describe --tags # 0.1.0-dev-93-g1416689
To get the most recent annotated tag:
git describe --abbrev=0
From a remote repository not cloned locally🔗
This one is a bit more tricky, and doesn't guarantee a 100% accurate result. You can do something like so to get the latest tags:
git ls-remote --tags --sort=v:refname <remote-git-repo>
# Example
git ls-remote --tags --sort=v:refname https://gitlab.com/InuitViking/imms.git
As you will see, you'll get it sorted in alphabetical order, and the output will be look something like below (IMMS as an example):
# ... Cut for brevity
6d26269573bbcac3c3bc12826f90821a4e494018 refs/tags/2024.05.07.21
8196c58090e1fd4b95897f9581650d6a0d0d50fd refs/tags/2024.05.07.22
261ab8ee0bac7f3f1f608559239ef2b9a1811fd6 refs/tags/2024.05.07.23
da9b9b04c95507e67d3d412827d5a5436f05706f refs/tags/2024.05.07.24
It takes every single tag made on that project and print it in the terminal with each tag its own line.
To get the latest tag, you can pipe it to tail
:
git ls-remote --tags --sort=v:refname <remote-git-repo> | tail -n 1
# Example:
git ls-remote --tags --sort=v:refname https://gitlab.com/InuitViking/imms.git | tail -n 1
In the case of IMMS, that last line (at the moment of writing), will look like this:
da9b9b04c95507e67d3d412827d5a5436f05706f refs/tags/2024.05.07.24
But if you only want the tag itself, and not the references and without the hashes, you could do something like so:
git ls-remote --tags --sort=v:refname <remote-git-repo> | tail -n 1 | awk '{print $2}' | cut -d "/" -f 3
# Example
git ls-remote --tags --sort=v:refname https://gitlab.com/InuitViking/imms.git | tail -n 1 | awk '{print $2}' | cut -d "/" -f 3
As with IMMS, at the moment of writing, the output will look like so:
2024.05.07.24
BUT there's of course a caveat! What if you have tags that aren't numeric? What if you get "double" tags where every "duplicate" tag is followed by a \^{}
? What if every tag starts with a "v"?.
Well, the ^{}
is easy to fix by adding grep -v "\^{}"
to the mix. To get the numbered version with or without v
prefix, could be matched by using grep 'v[0-9].\|[0-9].*'
.
The full command would then look like this:
git ls-remote --tags --sort=v:refname <remote-git-repo> | awk '{print $2}' | grep -v "\^{}" | cut -d "/" -f 3 | grep 'v[0-9].\|[0-9].*' | tail -n 1
# Example:
git ls-remote --tags --sort=v:refname https://gitlab.com/InuitViking/imms.git | awk '{print $2}' | grep -v "\^{}" | cut -d "/" -f 3 | grep 'v[0-9].*\|[0-9].*' | tail -n 1
But what does it do? Let's split the command up in list form below; it's making use of five commands and is piped five times. That's a lot. Explanation below, sorted in order of the above command, and sectioned for every pipe
git
: The version control command you normally would use to commit withls-remote
: List references in a remote repository--tags
: Limit the references to only tags.--sort=v:refname
: Treat the references as versions
awk
: In this case, see it as the "filtering program"'{print $2}'
: Print only the second column of the piped input
grep
: Used to search in plaintext by using regex-v "\^{}"
: Invert match; basically show all the things that don't contain^{}
cut
: Used in this case to cute parts from piped data-d "/"
: Cut via the delimiter/
-f 3
: Cut up to the third field- This is because we're cutting text that looks like so, which as three fields if
/
is the delimiter:refs/tags/2024.05.07.9
- This is because we're cutting text that looks like so, which as three fields if
grep
: See above'v[0-9].\|[0-9].*'
: This is the regex we use:v[0-9].*
matches any text containing character "v", followed by any digit, followed by a dot, followed by anything\|
: a basicOR
operator[0-9].*
matches any text containing any digit, followed by a dot, followed by anything
tail
: Output the last parts of the piped input-n 1
: output only the last single line of the inpit
You may also look at explainshell.com for a more in depth explanation.
The second grep could probably be improved, and if someone has a better way of doing it, please reach out to me on my website.