Invoking Beyond Compare via Git Bash with diff file as output - bash

I need some help adding arguments to the Git difftool.
I have Beyond Compare (BC) configured as a diff tool for Git. If I invoke the following line, Beyond Compare will successfully open with a diffed file:
git difftool
What I would like to do is invoke a Beyond Compare diff from Git Bash but using the command-line arguments Beyond Compare allows. For example, I'd like to set the report file BC uses to dictate the output format. I'd also like to dictate the output file, while hopefully dictating that the output file contains a filename similar to the file being compared, such as .html.
BC's command line form is: BC /silent
Any suggestions on how I can get the diff tool to do something like:
git difftool
Thanks!!

Related

More efficient way to parse git commands?

In-short: would like prompt to appear faster, although it's not sluggish.
Making a custom prompt for my bash terminal; the following list is in my /etc/bash.bashrc
I already use the "gitstatus" repo, which speeds up certain git commands. I think slowdowns come from the number of commands themselves. I want to know if I can generally use LESS git commands to do the same thing.
Here is a list of everything I do:
Obtain branch (if head detached, commands requiring it skipped)
Check for upstream
git rev-list --left-right --count "$branch"..."$upstream" to check if ahead or behind
Check for stashes
EDIT: Disregard #5. I called command #8 first, obtained this information, and appended #5 to PS1 before command #8
Check for dirty branch (done separately; I know #8 provides this info, but this command is called earlier on, and I like the symbol there)
Check for remote
Check for untracked files (separately than the bullet below, as they are located early in the prompt as I treat them as a higher priority "problem")
All at once check for modified, added, removes, or unmerged files by parsing git status -s
These are run using one git command per line. Will provide an image if needed as well.
On Bash for Windows terminal.
The answer to my own extremely specific question:
In my case, I'm trying to parse git status -s in function foo, and call function bar which detects if untracked files exist. The thing is, bar's output is appended to PS1 before foo's. It seems fine, but I'm trying to minimize the amount of git commands called every time in my bashrc. So, insteading of parsing git status -s in foo and then separately finding if untracked files exist in bar, I can call foo, create a untracked_files_exist variable, and make it true if such is given by git status -s. Then I can call bar after, use this untracked_files_exist how I want, and separately append the functions' outputs to PS1 in whichever order after both are called.
if that doesn't make sense:
If you want a fast prompt, call a parse-able git function that displays as much information as possible. If you want the prompt to contain such information in a different order than the git command outputs, don't append to PS1 INSIDE of the parsing functions. Do so AFTER so you have control over the order of the prompt.

Output from git log gets lost when piped to file - what am I missing?

I am trying to get some information about some git commits via the command line as part of a larger automated tool I am building. The information I want is available via this git log command:
git log --branches --graph --oneline --parents
which produces this output:
This is great, because this has the hashes and tags that I want, as well as the commit messages. However, when I pipe this to a file, the stuff in the brackets seems to somehow get lost. I'm not too interested in the colour, but I do want just the plain text as I would expect from any *nix-like program.
This is the output I seem to get instead, which omits some of the output I want (eg, the tag information):
I'm not sure how or why this information gets lost when being piped somewhere. I feel like this might be something incredibly simple and obvious.
I experience the same problem whether I do this in Bash on Arch Linux (with the latest version of git) or in the MINGW64 Bash environment in Windows.
Question: How can I completely capture git log's output without losing the information that is being lost when piping to a file?
You need to add the --decorate option to your log command. Set it either as --decorate=short or --decorate=full.
It appears in your config you've probably got log.decorate set to auto, which means that tags and such are displayed (in short form) when writing to the terminal, but not to a pipe or other file.
Similarly there are config values and command options that govern if (and when) color codes are output; so
git log --branches --graph --oneline --parents --decorate=short --color=always
would output the tags and colors even when redirected to a file.
Note that when scripting you should probably include these options on the command line rather than make assumptions about what config values are set. Depending on what you do with the output, log may or may not be the best command to use in scripting anyway, as git commands are somewhat divided into those meant for human consumption vs those mean for scripting.
Your git command:
git log --branches --graph --oneline --parents
does not produce the same output for me that you show in your first example. It does, however, produce output similar to the second example. The ref names in the brackets (branches and tags) are included when you add the --decorate option. (Here's the documentation.)
Note that your git log format can be controlled in your ~/.gitconfig file. For example, the format you've shown in your question looks like it might be achieved with options like this:
git log --decorate --graph --all --format='%C(auto,yellow)%h%C(auto,reset) %C(auto,yellow)%p%C(auto,reset) %C(auto,red)%d%C(auto,reset) %s %C(auto,green)%an%C(auto,reset) (%C(auto,cyan)%ar%C(auto,reset))'
If you are trying to automate things, you can specify a format that is better tuned to your requirements. Check the git documentation for pretty-formats for details. In particular, look for the %C format, and the %C(auto,…​) notation, which causes colour controls to be used only if the command is run from a terminal.
If you always want to generate the colour information regardless of whether you're using git log interactively, you can remove each ocurrence of auto, in the above line (or alias).

git log --grep does not work in windows

Is there any equivalent for "git log --grep="STRING" in windows?
I've written a python program for linux which requires a reading of commit logs that contain certain string from the git object. This worked fine in linux, but when I ran the same program in windows, git log --grep="STRING" catches nothing.
Here's the code snippet. (fetcher.py)
import os
...
os.chdir(DIRECTORY) # where git obj is
command = "git log --all --grep='KEYWORD' > log.txt"
os.system(command) # run the command in the shell
...
It seems that git internally uses the linux grep for the "--grep" argument such that Windows cannot run this correctly as it misses grep.
Thanks for your help.
As I am not getting any answer for 24 hrs,
I suggest my own solution, which does not utilize grep.
Because git log itself runs without any problem,
I just ran the command without the --grep='STRING' option, then read the output from the shell (or a file) to filter the commit logs which contain 'STRING' by the use of regular expression.
import os
import re
command = "git log --all > log.txt"
os.system(command) # run the command in the shell and store output in log.txt
with open('log.txt', 'r') as fp:
gitlogoutput = fp.readlines() # read the redirected output
if gitlogoutput:
commits = re.split('[\n](?=commit\s\w{40}\nAuthor:\s)', gitlogoutput)
# it splits the output string into each commits
# at every '\n' which is followed by the string 'commit shahash(40bytes)\nAuthor: '
for commit it commits:
if 'KEYWORD' is in commit:
print commit
The approach requires you to add some code, but I believe it does the same thing as the original command does. For better results, you can change the last if statement which is,
if 'KEYWORD' is in commit:
into something that can do more sophisticated search e.g. re.search() method.
In my case, this produced exactly the same result as that of --grep="KEYWORD"
Still, I appreciate your help :)
It seems that git internally uses the linux grep for the "--grep" argument such that Windows cannot run this correctly as it misses grep.
It certainly can, provided your %PATH% includes <git>/usr/bin (which has 200+ Linux commands compiled for Windows)
See this simplified path:
set G=c:\path\to\latest\git
set PATH=%G%\bin;%G%\usr\bin;%G%\mingw64\bin
set PATH=%PATH%;C:\windows\system32;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\
Add the PATH for python, and you can "Linux grep" without any issue.
In Windows, use the following format (replacing the = sign with a space):
git log --grep "STRING"

Git command line and batch file have different output

I'm creating a simple, single line batch file to run a git log in my preferred format. When I'm in PowerShell, I type:
git log --pretty=format:"%ai%x09%H%x09%s" > commitlog.csv
And it gives me exactly the output I want. It's the commit author's date and time in ISO format, followed by a tab, followed by the full SHA Hash, followed by a tab, followed by the notes/description. It opens in Excel exactly the way I want.
I tried to make a simple batch file to do the exact same thing so I wouldn't have to remember the format string or search the command history (which occasionally gets cleared, anyway). I noted that I had to use a double percent, %% to replace all the percent signs.
In one version of the batch file I have this line:
git log --pretty=format:"%%ai%%x09%%H%%x09%%s" > commitlog.csv
Which I noted echos the command like this:
git log --pretty=format:"%ai%x09%H%x09%s" 1>commitlog.csv
Which has a "1" interjected into it for some reason, but oddly creates a file with the information, just excluding the tabs, so it all runs together. I read that greater than '>' needs to be preceded by a carat, like so '^>'
So, in the next version of the batch file I changed the line to this:
git log --pretty=format:"%%ai%%x09%%H%%x09%%s" ^> commitlog.csv
Which echos the command like this:
git log --pretty=format:"%ai%x09%H%x09%s" > commitlog.csv
Which I've stared at for a long time, many times, and appears to be EXACTLY what I type in PowerShell, and I would expect to get the same result, but instead I get an error message:
fatal: ambiguous argument '>': unknown revision or path not in the
working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
What am I doing wrong?
The git log --pretty=format: command is terminating each line with just a newline (0x0A). Most tools on Windows (like Notepad) expect lines to be terminated with a carriage return (0x0D) and and newline. However, cmd has special handling for just a newline that makes the console output look pretty.
Thus, the batch file should look something like this:
git log --pretty=format:"%%ai%%x09%%H%%x09%%s%%x0D" > commitlog.csv
Notice the extra %%x0D to add the carriage return manually. As you found out already, the %% is needed to escape the single % inside of a batch script.
1> and just > are basically equivalent here. 1 is just the numeric value for stdout (compare to 2 for stderr), but the default is to redirect stdout. Cmd is just normalizing before printing to command that its going to run.
Minor nit: you may want to redirect to commitlog.tsv, as the values are separated by tabs, not commas. :-)
Git on Windows is often plagued by these sort of newline issues, so be on the look of for them elsewhere.

Git diff without comments

Let's say I added two lines to the file hello.rb.
# this is a comment
puts "hello world"
If I do git diff, it will show that I added two lines.
I don't want git to show any line which is a Ruby comment. I tried using git diff -G <regular expression>, but it didn't work for me. How do I do git diff so that it won't show any Ruby comments?
One possibility would be (ab)using git's textconv filters which are applied before the diff is created, so you can even transform binary formats to get a human-readable diff.
You can use any script that reads from a file and writes to stdout, such as this one which strips all lines starting with #:
#!/bin/sh
grep -v "^\s*#" "$1" || test $? = 1
(test $? = 1 corrects the exit code of grep, see https://stackoverflow.com/a/49627999/4085967 for details.)
For C, there is a sed script to remove comments, which I will use in the following example. Download the script:
cd ~/install
wget http://sed.sourceforge.net/grabbag/scripts/remccoms3.sed
chmod +x remccoms3.sed
Add it to your ~/.gitconfig:
[diff "strip-comments"]
textconv=~/install/remccoms3.sed
Add it to the repository's .gitattributes to enable it for certain filetypes:
*.cpp diff=strip-comments
*.c diff=strip-comments
*.h diff=strip-comments
The main downside is that this will be always enabled by default, you can disable it with --no-textconv.
Git cares a lot about the data that you give to it, and tries really hard not to lose any information. For Git, it doesn't make sense to treat some lines as if they haven't changed if they had.
I think that the only reasonable way to do this is to post-process Git output, as Dogbert had already shown in his comment.

Resources