create git pull -f multi-token alias - bash

I'd like to make an alias like this:
'git pull -f'='MYBRANCH="$(git rev-parse --abbrev-ref HEAD)"; echo "origin/${MYBRANCH}" | git reset --hard'
In simpler terms, it's a git reset --hard origin/my_current_branch.
But bash tells me that git pull -f cannot be a valid alias (probably because there are spaces in it?). Is there a way to get around this?

If I understand correctly, you want to perform the following steps with the alias:
Get the name of your current branch
Fetch the corresponding branch from origin
Hard-reset to the remote branch
Instead of a Bash alias to do this,
I suggest to define a Git alias.
To do that, add this in the [alias] section in your ~/.gitconfig:
myreset = "!f() { br=$(git rev-parse --abbrev-ref HEAD); git fetch origin $br; git reset --hard origin/$br; }; f"
This way, you can run git myreset to perform the operations.
(Feel free to rename "myreset" to whatever you prefer.)

Related

What is significance of git hard-reset after git pull

One of my managing projects is using Git and Jenkins for deployment. In the Jenkins job they have specified a hard reset after git pull operation .I dont understand why it is using there. If there is no codes need to commit it will run the below script in jenkins
git pull origin Production
git reset --hard dbb56hgf
cp -r <jenkins_work_directory> <domain_document_root>```
They probably want to make sure that there are no local changes before running the rest of the script.
The purpose of the “git reset” command is to move the current HEAD to the commit specified (in this case, the dbb56hgf itself, one commit before HEAD and so on)
git reset --hard HEAD (going back to HEAD)
git reset --hard HEAD^ (going back to the commit before HEAD)
git reset --hard HEAD~1 (equivalent to "^")
git reset --hard HEAD~2 (going back two commits before HEAD)

Is there a way to add multi steps to a git alias?

I'm going to create an alias that does this:
I've added it to my git-bash .bash_profile but I'd like to see if there is a way to add it as an alias so I don't have to use git bash
Git finish will push to current branch # Eg. gf "commit message"
gf() {
CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
git add . && git commit -m "$1" && git push origin "$CURRENT_BRANCH"
} # Git merge # Eg. gm branch-name
gm() {
git merge "$1"
} # Git checkout # Eg. gc branch-name
gc(){
git checkout "$1" && gp
}
You could create a "Git-Subcommand" the name of this executable must be in this Format: git-{{ Name }} eg: git-acommit. This File must be located in one the Directories listed in $PATH, you can now execute git acommit and git will search for it in you $PATH.
To use this than in an alias simply run git config --global alias.gf acommit and you are finished. Please note: the alias step is unnecessary since you can name your file how you want, so you could also name it git-gf instead of git-acommit.
But without creating a separated file it's impossible to stack commands in a git alias.
Or you could use GitAlias to create an alias that executes a function or multiple Commands.
For an example check out the Recovery examples Section.

How to use git alias with shell function to build a commit message

I'm trying to create a git alias to automate my PR merge and approval.
The complete git command is this:
git checkout master && git sync && git merge --no-ff -m 'Merged in hotfix/X-3144 (pull request #1112)' remotes/origin/hotfix/X-3144
Where X is the BitBucket prefix for the issue. Reading other stack overflow questions, I came up with this:
mergeto = "!f() { git checkout $1 && git sync && git merge --no-ff -m 'Merged in {$2}/B2B-{$3} (pull request #{$4})' remotes/origin/$2/X-$3;}; f "
So, naturally I'm using this to merge a PR that has conflicts. After I resolve these conflicts, I issue a git commit and git brings up nano with my previously typed commit message. My goal here is that the commit message is constructed using my parameters. So, for an example, if I use:
git mergeto master hotfix 123 1120
My final commit message was supposed to be "Merged in hotfix/X-123 (pull request #1120)" but instead I get a "Merged in {$2}/X-{$3} (pull request #{$4})"
How can I specify the parameters in such a way that this can work?
I Read a few stack over flow posts that show how to use a shell function inside a git alias, but couldn't find an example of escaping the text with parameters.
Using John Szakmeister and eftshift0 suggestions, I got it working by escaping double quotes with backlash:
mergeto = "!f() { git checkout $1 && git sync && git merge --no-ff -m \"Merged in $2/B2B-$3 (pull request #$4)\" remotes/origin/$2/X-$3;}; f "
Thanks for your help!

howto find out which git submodule current directory belongs to

setup
i have a git repo located in /home/v/git_repo, in which i have a submodule localted in subdirectory ./a/b/c.
$ cat /home/v/git_repo/.gitmodules
[submodule "foo/bar"]
path = a/b/c
url = git#github.com:username/repo.git
having the full path or only the in-repository subpath (that i have implemented in helper script git-where-in-repo-am-i-currently)
$ pwd
/home/v/git_repo/a/b/c/something
$ git where-in-repo-am-i-currently
a/b/c/something
question
i want to find out (preferably in fish) which submodule this path belongs to: e.g
$ git which-submodule (pwd)
foo/bar
to later use it to query that submodules status like
$ git -C (git rev-parse --git-dir)/modules/(git which-submodule) status
on branch master
Your branch is up to date with 'origin/master'
and ultimately display this information in my prompt (that part is already implemented)
what i tried
parsing the output of
$ git -C (git rev-parse --show-toplevel) config --file=.gitmodules --get-regexp "path"`
submodule.foo/bar.path a/b/c
and comparing my sub-directory path to that of a submodule, but it was rather a mess, with splitting pathes into arrays and all kinds of hacks
For the usual setup you've described here, with the worktree nesting matching the submodule nesting, you can
mytoplevel=`git rev-parse --show-toplevel`
abovethat=`git -C "$mytoplevel"/.. rev-parse --show-toplevel`
Then,
echo ${mytoplevel#$abovethat/}
will get you the submodule path in the superproject, or you can
echo ${PWD#$abovethat/}
to get your current directory's path relative to the superproject.
So:
me=`git rev-parse --show-toplevel`
up=`git -C "$me"/.. rev-parse --show-toplevel`
subpath=${me#$up/}
git -C "$up" config -f .gitmodules --get-regexp '^submodule\..*\.path$' ^$subpath$
gets you the current repo's submodule name and path from the config entry in its superproject.
Git can be useful in any imaginable build system, though; it doesn't impose restrictions on how things outside its remit are set up. So short of an exhaustive search of the filesystem namespace you can't be sure you've found everybody using any worktree as a submodule checkout, there's just no reason for Git to care how a repository is used.
For instance, if multiple projects all need to run off the same submodule rev, you can have a single repo and worktree serve as a shared submodule for them all: rather than have to go through every single one of them and do synchronized checkouts, and then trusting that you haven't missed one, just use one repo, with one worktree, and point everybody using it at that.
For workflows with that need, this can be compellingly better than the usual setup, all users by definition see a synchronized, current submodule revision and any client who needs to know "what's new" with an update can e.g. git -C utils diff `git rev-parse :utils` HEAD, every submodule user effectively has their own tracking branch and can use all of Git's tools to help stay current or resolve conflicts.
So, to recreate your setup, I do:
git init git_repo; cd $_
mkdir a/b; git init a/b/c; cd $_
mkdir something; touch something/somefile;
git add .; git commit -m-
cd `git -C .. rev-parse --show-toplevel`
git submodule add --name foo/bar ./a/b/c -- a/b/c
git add .; git commit -m-
Then I get this when I try it:
$ find -print -name .git -prune
.
./a
./a/b
./a/b/c
./a/b/c/something
./a/b/c/something/somefile
./a/b/c/.git
./.gitmodules
./.git
$ git grl
core.repositoryformatversion 0
core.filemode true
core.bare false
core.logallrefupdates true
submodule.foo/bar.url /home/jthill/src/snips/git_repo/a/b/c
submodule.foo/bar.active true
$ cd a/b/c/something
$ me=`git rev-parse --show-toplevel`
$ up=`git -C "$me"/.. rev-parse --show-toplevel`
$ subpath=${me#$up/}
$ git -C "$up" config -f .gitmodules --get-regexp '^submodule\..*\.path$' ^$subpath$
submodule.foo/bar.path a/b/c
$ echo $me $up $subpath
/home/jthill/src/snips/git_repo/a/b/c /home/jthill/src/snips/git_repo a/b/c
If there's a difference between this setup and what you've described, I'm missing it, I've got the directory structure, the submodule name, the start directory... if you'll step through that and find where the setup or results diverge from yours I think that'd help.

How to reset the entire Git repository, and not only the "Master" branch, to match Remote?

What the title says.
I want to reset each and every local branch to match my Remote repository, including deleting some branches and tags which only exists locally, without having to delete everything and cloning from scratch. All I could find are instructions on how to reset a specific branch, but not the entire repository.
Even better if it can be done from the TortoiseGit Shell extension. But I'm also fine with the command line.
You can do it by following commands:
git checkout --orphan #
git fetch <Remote> refs/*:refs/* --refmap= --prune --force
where <Remote> is remote repository you want to use. You simply fetch all remote refs (refs/*:refs/*) with --prune and --force flags to remove and force update local references.
The following line will reset all local branches that have a configured upstream branch to the state of the upstream branch
git checkout #{0} && git for-each-ref refs/heads --format '%(refname:strip=2)' | xargs -ri sh -c 'git rev-parse {}#{u} >/dev/null 2>&1 && git branch -f {} $(git rev-parse {}#{u})'
You will end up with a detached HEAD due to the first command, because you cannot reset the currently checked out branch, so checkout the branch you want to have in your working directory after doing this.

Resources