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

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.)

Related

Check if git branch contains commit with given subject

Given an exact subject line of a commit I want to know if a branch contains a commit with that subject.
What I have right now is: git log --format="%s" -F --grep="$msg" "$branch" | grep -Fq --max-count=1 -- "$msg"
I.e. search the log with a fixed-string grep and print the subject. Then search that subject with the same fixed-string and stop at the first match.
The 2nd grep is required because git log --grep may find the pattern anywhere in the commit message (e.g Fixes "$msg")
However this has the downside that it seemingly always walks the entire history of that branch which takes quite long.
As a test I ran git log --format="%s" -F --grep="$msg" "$branch" | grep -Fq --max-count=1 -- "$msg" and git log --format="%s" -F --grep="$msg" "$branch" and they both took the same time although the commit to grep for is found/printed very fast (for the 2nd)
So is there a way to directly find a commit in a branch by a given subject (using fixed strings as $msg comes from another command and may contain regex-like characters) faster or at least make my log-grep-pipe exit faster (on success)?
Try this:
git log --format="%s" "$branch" | grep -Fqx --max-count=1 -- "$msg"
Here x will match the entire line.. and max-count will return the first match.

Output first line of temporary file

I am writing a script to checkout the latest git commit with the word "merge" inside the commit message. I am trying to output the latest git commit line to see if my script is working so far
tempfile=$((mktemp))
tempfile2=$((mktemp))
git log --oneline >> $tempfile
grep -i "merge" $tempfile | head -1 > $tempfile2
cat $tempfile2
I was expecting the script to output just one line containing "merge" however it outputs the whole log. I actually just want to take the commit id and git checkout the latest "merge" file to a detached head state. If anyone could help me with what to do next I would greatly appreciate it. Thank you

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/,,'

Bash: using the output of one command in the other

I have the following requirement here: Fetch all the commits from our SVN from the last two years and list the title of all the JIRA issues that had code committed. Our commit rules are pretty strict, so a commit must start with the JIRA code, like: COR-3123 Fixed the bug, introduced a new one
So, I wrote the following shell script to get this working:
svn log -r{2012-04-01}:{2014-04-01} | grep "COR-" | cut -f1 -d" " | sort -u
This gets me all the JIRA codes.
But now I want to use these in the following command:
wget --quiet --load-cookies cookies.txt -O - http://jira.example.com/browse/{HERE} | sed -n -e 's!.*<title>\(.*\)</title>.*!\1!p'
Ie: get the JIRA page via wget and parse out the title... (I have already cached my login credentials to use with wget in cookies.txt)
and obviously to the location {HERE} I want to insert the code obtained from the first list. Doing this via a two step (step 1: get list, step 2 iterate via list) script (python, perl, ... ) is not a problem, but I'd like to know if it's possible to do it in ONE step, using bash :)
(Yes, I know there is JIRA rest API)
You can use xargs to pass the parameter to wget:
xargs -I {} wget http://jira.example.com/browse/{}

Yanking text from the previous stdout onto the command line

I'd like to set up my Bash in such a way that I could yank text from the previous command's stdout. The example use case I'll use is resolving conflicts during a git rebase.
$ git status
# Not currently on any branch.
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: app/views/report/index.html.erb
#
$ vim app/views/report/index.html.erb
# .... edit, resolve conflicts ....
$ git add <Alt+.>
The problem is that the easiest way to grab the filename for the 2nd command (vim ...) is to move my hand over to the mouse. One option is screen, but that has its own set of issues as a day-to-day shell. (Not the least of which is that I use and abuse Ctrl+A as a readline shortcut)
Where could I start at making this work for me? Ideally I'd like to be able to pull the Nth line from the stdout of the previous command somewhere that I can manipulate it as a command.
Other than using the mouse, the only way I can think of is to use grep, sed and/or awk, perhaps with tee and/or a Bash function and process substitution and/or process and/or command substitution:
vim $(git status | tee /dev/tty | grep ...)
or
var=$(git status | tee /dev/tty | grep ...)
vim "$var"
git add "$var"
The tee allows you to see the full output while capturing the modified output. Creating a function would allow you to easily pass an argument that would select a certain line:
var=$(some_func 14)
etc.
The disadvantage is that you have to do this from the start. I don't know of any way to do this after the fact without using screen or some other output logging and scripting a rummage through the log.
I don't know of a good, clean solution, but as a hack you could try the script command, which logs all input and output to a file. For GNU script:
$ script -f
Script started, file is typescript
$ ls -1
bar
baz
foo
typescript
$ echo $(tail -3 typescript | head -1)
foo
pipe the output through sed:
git status | sed -n '5p'
to get the 5th line

Resources