bash substring - combine command and slicing - bash

I want to get first 8 characters of latest git commit hash. To retrieve git HEAD hash, I use git rev-parse HEAD. I've found here that I can get a substring using ${string:position:length}. But I don't know how to combine them both (in a one-liner, if possible). My attempt
${"`git rev-parse HEAD`":0:8}
is wrong.

You cannot combine BASH substring directive by calling a command inside it:
Instead you can use:
head=$(git rev-parse HEAD | cut -c1-8)
Or else old faishon 2 steps:
head=$(git rev-parse HEAD)
head=${head:0:8}

Using sed:
git rev-parse HEAD | sed 's/^\(.\{,8\}\).*$/\1/g'

out=`git rev-parse HEAD`
sub=${out:0:8}
example:
a="hello"
b=${a:0:3}
bash-3.2$ echo $b
hel
its a two step process, where first the output of git command is extracted, which is a string. ${string:pos:len will return the substring from pos of length len

Related

Git Extract modification in one string line

Any good combination of Bash + git diff to get in one line the only change that I made in my file?
I'm using form Jenkins DSL, and the best that I get so far is this
"${sh(script: "git diff --shortstat", returnStdout: true)}".trim() == "1 file changed, 1 insertion(+), 1 deletion(-)"
But what I would love to have is the "hello world" text that I just add into one of the files.
If you've got just one hunk,
git diff -U0 | sed 1,/^##/d
and strip the leading character off.

GIT: How to search through older versions of a file and list all versions that match the search criteria?

I have a repo that contains a certain file. I need to create a git script that searches through all the previous versions of this file and lists the commit SHAs that contain a specific string.
I want to have a list of all the commits that in their version that string exists.
The best answer I could find is here (but not good enough): https://stackoverflow.com/a/4705617/4441211
This solution is not good enough because this only finds where there was a change (i.e the search term was added or removed). Does anybody have a better idea how to do this?
To look for a pattern <pattern> in a file <path/to/file> within a commit <commit> : use git grep
git grep -e <pattern> <commit> -- <path/to/file>
Check git help grep for more details : many options are copied of the original grep command (-l to only list file names, -q to drop output ...)
If your intention is to scan all commits looking for a string (not just the commits where a change occured) :
git rev-list HEAD will give you the list of all commits in the ancestry of your active branch,
write a loop to repeatedly call git grep on these commits.
For example :
git rev-list HEAD | while read sha; do
git grep -q -e <pattern> $sha -- <path/to/file> && echo $sha
done

To list the branch names based on branchtype

I have git branches under the type feature ad release i want to display the release branches when i give the input as release or the possible string(re, rel..etc) same as to feature branch and other branch types as well. I have a command to give the branch type now after when i get the branch type as release or feature based on my input i want to display the branch names under that type i choose.
Command I have:
#!/bin/bash
read branchtype
git branch --remote --list origin/* | grep $branchtype | cut -d '/' -f2 | sort -u
#!/bin/bash
read branchtype
git branch --remote --list origin/* | grep $branchtype | cut -d '/' -f2 | sort -u
First, I think you will have a much easier time if you use arguments to the script rather than reading stdin.
Second, why use a global pattern (origin/*) to return everything just to filter with a separate program (grep)?
Finally, maybe I misunderstand, but I imagine branch names like origin/feature/newThing and origin/feature/coolUpgrade and origin/bugfix/oopsie. Selecting for feature, that cut -d '/' -f2 | sort -u is just going to spit out feature and nothing else. (maybe you wanted -f3?)
Try this:
(create the file ~/bin/branchFilter first...)
$: cat ~/bin/branchFilter
#!/bin/bash
git branch --remote --list origin/*$1*
Then use it. (Make sure you set executable permissions.)
$: branchFilter # no argument
origin/HEAD -> origin/master
origin/bugfix/bar
origin/bugfix/foo
origin/dev
origin/feature/otherName
origin/feature/test
origin/hotfix/thisIsBroken
origin/master
origin/preprod
origin/production
origin/qa
origin/sit
origin/uat
origin/wip
$: branchFilter feature
origin/feature/otherName
origin/feature/test
$: branchFilter bugfix
origin/bugfix/bar
origin/bugfix/foo
$: branchFilter fix
origin/bugfix/bar
origin/bugfix/foo
origin/hotfix/thisIsBroken
If you really need the origin/ off the beginning, trim it with sed.
$: cat ~/bin/branchFilter
#!/bin/bash
git branch --remote --list origin/*$1* |
sed 's,origin/,,'
$: branchFilter fix
bugfix/bar
bugfix/foo
hotfix/thisIsBroken
If you just have to read from the input (I think it's a bad structure, but your program), it still works the same way.
$: cat ~/bin/branchFilter
#!/bin/bash
read str
git branch --remote --list "origin/*$str*" |
sed 's,origin/,,'

How to redirect part of output of git subtree push

git subtree push ... produces a lot of output. Although it is ok, using them on gitlab-ci is a nightmare.
I find it awful because the outputs are displayed line by line:
git push using: git#gitlab.xxx.com:micro/service.git feature/ci
1/207 (0)
2/207 (1)
3/207 (2)
4/207 (3)
5/207 (4)
6/207 (5)
7/207 (6)
8/207 (7)
...
Everything up-to-date
How can I hide 1/207 (0) without hiding the rest?
I tried
with the -q parameter, doesn't work
to pipe the output to a regex to "hide" the annoying lines:
$ git subtree push ... | while IFS= read -r line; do if [[ "$line" =~ [0-9]+/[0-9]+ ]];then : ; else echo "$line"; fi done doesn't work
?
You can try a grep to find and discard the line you don't want. But this is very specific to that query. Are you sure you don't want to hide some line class instead of just a string?
For your specific question, try
git subtree push ... | grep -v "1/207 (0)"
UPDATE:
Given the clarification, just adapt the search term and use regular expressions:
git subtree push ... | grep -v -e '[0-9]+/[0-9]+'

git pull always fails, but git fetch/merge are fine

When I git pull in any repository, I always get the following merge error:
aetherboard:shwangster shwangster$ git pull -v
From github.com:sirspinach/shwangster
= [up to date] master -> origin/master
merge: 012012012012012012012012012012012012012012012012012012012012 - not
something we can merge
On the other hand, git fetch and git merge origin/master work like a charm. So I've been able to work around this problem for a while. However, I needed to update brew today, and the same error prevents me from doing that.
Here is the output from brew update, which shows git again attempting to merge with the mysterious 0120120120120....
aetherboard:gitrepos shwangster$ brew update
merge: 012012012012012012012012012012012012012012012012012012012012 - not
something we can merge
Error: Failure while executing: git pull -q origin refs/heads/master:refs/remotes/origin/master
There's a clue in the other (pretty much exact duplicate) question that Kaz noted in a comment, that the problem went away when pyenv was taken out of $PATH.
Here's the bit from the pull script that takes the FETCH_HEAD trace and turns it into an argument to git merge (or to git rebase when doing a rebasing pull):
merge_head=$(sed -e '/ not-for-merge /d' \
-e 's/ .*//' "$GIT_DIR"/FETCH_HEAD | \
tr '\012' ' ')
(By the way, note that those are tabs before and after not-for-merge and in the second -e argument to sed. Cut-and-paste generally turns tabs into spaces, and did here.)
I imagine the sed part is working correctly and the failure occurs with the tr invocation. In fact, it looks like whatever tr is being used, is simply spitting out the 012 string (for a total of 60 characters, or 20 instances of the three-character group—not sure how that happens given that the sed output is, or should be, a 40-character SHA-1).
If your shell is sh or bash, see what:
$ type tr
prints. If you use a csh variant, which tr will show you what it will run. (I'm not sure off-hand what to use for dash and zsh.) If you get something other than /usr/bin/tr, that may explain the problem. (If you do get /usr/bin/tr see what type sed or which sed says: these should be /usr/bin/sed.)

Resources