PowerShell - git checkout -B without reset or alternatives? - windows

Related to this question: git checkout -B without reset or alternatives?
I want to change branches, but create the branch if it doesn't exist. -B doesn't work, as I have un-pushed commits on the branches and don't want them to be reset.
How would you write this: git checkout branchname -- 2>/dev/null || git checkout -b branchname in powershell?

The equivalent of this shell command...
git checkout branchname -- 2>/dev/null || git checkout -b branchname
...in PowerShell would be this:
$branchname = "your-branch"
git checkout $branchname 2>&1 | Out-Null
if (-not $?) {
git checkout -b $branchname
}
It uses the $? automatic variable, to determine if the last command succeeded. Also, error stream redirection and Out-Null.
Note that in PowerShell 7 (Core), || and && are also available, called pipeline chain operators.
git checkout $branchname || git checkout -b $branchname

Related

git config alias adding slashes

I'm creating an install script for a load aliases and git config is not playing nice with them
Here is the command in the shell script
git config --global alias.sync-fork '"!f() { oldhash="$(git rev-parse -q --verify refs/stash)"; (git fetch --all && git stash --include-untracked) && ( (git checkout "$(git default-branch)" && git pull && git merge upstream/"$(git default-branch)" && git push && git checkout -); [ "$(git rev-parse -q --verify refs/stash)" != "$oldhash" ] || git stash pop) }; f"'
When I run it and look in the ~/.gitconfig file, I see "\" everywhere and it doesn't work. Using echo, I can see the string I want. This is driving me crazy.
The most immediate problem is that you have too many quotes; '"..."' should just be '...' without the "s inside. However, I can't guarantee that you won't have more issues after you fix that one.
Instead of trying to escape your shell function by hand, have the shell itself do it for you using declare -f to serialize your function.
f() {
oldhash="$(git rev-parse -q --verify refs/stash)"
(git fetch --all &&
git stash --include-untracked
) && (
(git checkout "$(git default-branch)" &&
git pull &&
git merge upstream/"$(git default-branch)" &&
git push &&
git checkout -)
[ "$(git rev-parse -q --verify refs/stash)" != "$oldhash" ] || git stash pop)
}
git config --global alias.sync-fork '!'"$(declare -f f); f"
This does mean git will add some extra escapes to fit the function into proper config-file form, but when you use declare -f the output is guaranteed to be well-formed (at least if your /bin/sh is provided by bash).

Place command resulted by a git alias to bash history

The following git alias give a menu to select the remote and branch name for fetch command.
git config --global alias.fh '!git fetch $(git remote | rofi -dmenu) $(git branch | sd "^[\*]*[ ]*" ""| rofi -dmenu)'
The end result of this alias (shown by echo git fetch $(git remote | rofi -dmenu) $(git branch | sd "^[\*]*[ ]*" ""| rofi -dmenu)) is something like:
git fetch origin1 branch2
git fetch origin2 branch3
git fetch origin3 branch1
My issue is, in bash history I only get git fh when the alias is run. However, In history, I would like to have whatever was the end result of the last invocation of git fh (something like git fetch origin2 branch3).
How can I do that?

Git push to various repositories via bash script

I'm trying to create a bash script that iterates over 4 different folders (git repositories) and updates/pushes the changes for each one of them. I have the script mostly complete, except the authentication part.
Here's my current script:
#!/bin/bash
# Fetch username and password
echo "Please insert your git credentials!"
read -p 'Username: ' username
read -sp 'Password: ' password
# Check if you svn and git installed in your machine
if which svn &> /dev/null && which git &> /dev/null; then
# Store the current dir
CUR_DIR=$(pwd)
# Let the person running the script know what's going on.
echo "Pulling in latest changes for all repositories..."
for D in $CUR_DIR/*; do
if [ -d "${D}" ]; then
echo "${D}"
cd $(basename $D);
# Make sure SVN is on trunk branch and git branch is on master
SVN_BRANCH=$(svn info | grep '^URL:' | egrep -o '(tags|branches)/[^/]+|trunk' | egrep -o '[^/]+$')
GIT_BRANCH=$(git symbolic-ref --short HEAD)
if [ "$SVN_BRANCH"!="trunk" ] || [ "$GIT_BRANCH"!="master" ]; then
echo $CUR_DIR
echo "Make sure you're on SVN trunk branch and git master branch."
exit -1
fi
echo "Update SVN repository";
svn up
# Update git
git add .;
git commit -m "Update with the changes from svn trunk branch."
echo "Start pushing changes to main repository."
git push origin master
echo "Update git repository";
git pull origin master
# Update SVN
svn add .
svn commit -m "Update with changes from git master branch."
cd ..
fi
echo "Complete!"
done
else
echo "You need both svn and git CLI's installed to run this script!";
fi
As you can see, I'm already fetching the credentials in the beginning of the script, my problem is how can I use them to do the actions that need authentication, namely
git push origin master
git pull origin master
How can I build the git commands to make the authenticated request?

change directory in bash is not affecting the post-commit hook

i've made the following bash script to commit the parent repo after some change in submodule.
it's all about that the script want to cd .. to check the parent repo current branch but the problem is that the cd .. is not affecting the upcoming commands because i guess the subshell
i've tried to run
1- cd ../ && before each command
2- make alias but didn't succeed
3- run exec but the script didn't continued
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "post-commit".
commit_msg= git log -1 --pretty=%B
if [[ $(git branch | grep \* | cut -d ' ' -f2) == "int1177/next" ]]; then
cd ..
if [[ $(git branch | grep \* | cut -d ' ' -f2) == "B0/next" ]]; then
git add 6_Tests
git commit -m "bs esss"
echo "development branch B0/next has now new commit"
else
echo "development branch isn't B0/next"
fi
else
echo "current branch isn't int1177/next"
fi
Actually, this particular problem is not a bash issue, but rather a Git issue.
Why doesn't "cd" work in a shell script? is valid in general, and is a suitable answer to many other questions. But this particular post-commit hook is trying to chdir out of a submodule into its parent superproject, then make a commit within the parent superproject. That is possible. It may be a bad idea for other reasons—in general it's unwise to have Git commit hooks create commits, even in other repositories1—but in this particular case you're running into the fact that Git finds its directories through environment variables.
In particular, there's an environment variable GIT_DIR that tells Git: The .git directory containing the repository is at this path. When Git runs a Git hook, Git typically sets $GIT_DIR to . or .git. If $GIT_DIR is not set, Git will find the .git directory by means of a directory-tree search, but if $GIT_DIR is set, Git assumes that $GIT_DIR is set correctly.
The solution is to unset GIT_DIR:
unset GIT_DIR
cd ..
The rest of the sub-shell commands will run in the one-step-up directory, and now that $GIT_DIR is no longer set, Git will search the superproject's work-tree for the .git directory for the superproject.
As an aside, this:
$(git branch | grep \* | cut -d ' ' -f2)
is a clumsy way to get the name of the current branch. Use:
git rev-parse --abbrev-ref HEAD
instead, here. (The other option is git symbolic-ref --short HEAD but that fails noisily with a detached HEAD, while you probably want the quiet result to be just the word HEAD, which the rev-parse method will produce.)
1The main danger in this case is that the superproject repository is not necessarily in any shape to handle a commit right now. Edit: or, as discovered in this comment, is not even set up to be a superproject for that submodule, yet, much less to have a submodule-updating commit added.

How to write value1 || value2 in shell?

I would make a simple script in shell and put a default value in case the user enters nothing. Here is my script:
git add -A
git commit -m "checkpoint commit"
git push
I would make something like
git add -A
git commit -m ($1 || "checkpoint commit")
git push
You can use
git commit -m "${1:-checkpoint commit}"
If $1 is set, ${1:-checkpoint commit} will expand to the value of $1.
If $1 is not set, it will expand to whatever is after the :- (ie "checkpoint commit" in this example).

Resources