Annotated diff file with "<<<<<<< mine" and ">>>>>>> yours" type markers - diff

I am trying to create a diff file using the Linux diff command that has markers like this (taken from diff3 man page):
<<<<<<< mine
lines from mine
=======
lines from yours
>>>>>>> yours
This format is very intuitive for me and allows me to easily fix merge conflicts in vim and it works great when I am trying to merge three files (mine, yours and original) using diff3 but I would like the same format from plain diff. I was hoping this would be simple but I have not been able to get it. I have tried most of the main options (-e,--ed, etc.) and even tried to create a --changed-group-format but was unsuccessful.
Hopefully this is something simple that I just overlooked.
UPDATE:
Two file diff example with added line, removed line and conflict line:

You could play with the diff options. The shell script below
diff \
--unchanged-group-format='%=' \
--old-group-format='' \
--new-group-format='%>' \
--changed-group-format='<<<<<<< mine
%<=======
%>>>>>>>> yours
' \
orig.txt new.txt
Outputs
This has some stuff
in that gets
modified in
a later version
<<<<<<< mine
and there is a conflict
=======
and there is a conflict (like here)
>>>>>>> yours
about which version
should be used.
newline
For the files as in your screenshot. You could look more formatting options for the diff in a documentation, e.g. here.
One liner (works from command line, at least on linux):
diff --unchanged-group-format="%=" --old-group-format="" --new-group-format="%>" --changed-group-format="<<<<<<< mine%c'\\12'%<=======%c'\\12'%>>>>>>>> yours%c'\\12'" orig.txt new.txt

Related

How do I diff only certain files?

I have a list of files (a subset of the files in a directory) and I want to generate a patch that includes only the differences in those files.
From the diff manual, it looks like I can exclude (-x), but would need to specify that for every file that I don't want to include, which seems cumbersome and difficult to script cleanly.
Is there a way to just give diff a list of files? I've already isolated the files with the changes into a separate directory, and I also have a file with the list of filenames, so I can present it to diff in whichever way works best.
What I've tried:
cd filestodiff/
for i in `*`; do diff /fileswithchanges/$i /fileswithoutchanges/$i >> mypatch.diff; done
However patch doesn't see this as valid input because there's no filename header included.
patchutils provides filterdiff that can do this:
diff -ur old/ new/ | filterdiff -I filelist > patchfile
It is packaged for several linux distributions

Search for files & file names using silver searcher

Using Silver Searcher, how can I search for:
(non-binary) files with a word or pattern AND
all filenames, with a word or pattern including filenames of binary files.
Other preferences: would like to have case insensitive search and search through dotfiles.
Tried to alias using this without much luck:
alias search="ag -g $1 --smart-case --hidden && ag --smart-case --hidden $1"
According to the man page of ag
-G --file-search-regex PATTERN
Only search files whose names match PATTERN.
You can use the -G option to perform searches on files matching a pattern.
So, to answer your question:
root#apache107:~/rpm-4.12.0.1# ag -G cpio.c size
rpm2cpio.c
21: off_t payload_size;
73: /* Retrieve payload size and compression type. */
76: payload_size = headerGetNumber(h, RPMTAG_LONGARCHIVESIZE);
the above command searches for the word size in all files that matches the pattern cpio.c
Reference:
man page of ag version 0.28.0
Note 1:
If you are looking for a string in certain file types, say all C sources code, there is an undocumented feature in ag to help you quickly restrict searches to certain file types.
The commands below both look for foo in all php files:
find . -name \*.php -exec grep foo {}
ag --php foo
While find + grep looks for all .php files, the --php switch in the ag command actually looks for the following file extensions:
.php .phpt .php3 .php4 .php5 .phtml
You can use --cpp for C++ source files, --hh for .h files, --js for JavaScript etc etc. A full list can be found here
Try this:
find . | ag "/.*SEARCHTERM[^/]*$"
The command find . will list all files.
We pipe the output of that to the command ag "/.*SEARCHTERM[^/]*$", which matches SEARCHTERM if it's in the filename, and not just the full path.
Try adding this to your aliases file. Tested with zsh but should work with bash. The problem you encountered in your example is that bash aliases can't take parameters, so you have to first define a function to use the parameter(s) and then assign your alias to that function.
searchfunction() {
echo $(ag -g $1 --hidden)
echo $(ag --hidden -l $1)
}
alias search=searchfunction
You could modify this example to suit your purpose in a few ways, eg
add/remove the -l flag depending on whether or not you want text results to show the text match or just the filename
add headers to separate text results and filename results
deduplicate results to account for files that match both on filename and text, etc.
[Edit: removed unnecessary --smart-case flag per Pablo Bianchi's comment]
Found this question looking for the same answer myself. It doesn't seem like ag has any native capability to search file and directory names. The answers above from Zach Fogg and Jikku Jose both work, but piping find . can be very slow if you're working in a big directory.
I'd recommend using find directly, which is much faster than piping it through ag:
Linux (GNU version of find)
find -name [pattern]
OSX (BSD version of find)
find [pattern]
If you need more help with find, this guide from Digital Ocean is pretty good. I include this because the man pages for find are outrageously dense if you just want to figure out basic usage.
To add to the previous answers, you can use an "Or" Regular Expression to search within files matching different file extensions.
For example to just search a string in C++ header files [.hpp] and Makefiles [.mk] ) :
ag -G '.*\.(hpp|mk)' my_string_to_search
After being unsatisfied with mdfind, find, locate, and other attempts, the following worked for me. It uses tree to get the initial list of files, ag to filter out directories, and then awk to print the matching files themselves.
I wound up using tree because it was more (and more easily) configurable than the other solutions I tried and is fast.
This is a fish function:
function ff --description 'Find files matching given string'
tree . --prune --matchdirs -P "*$argv*" -I "webpack" -i -f --ignore-case -p |
ag '\[[^d].*' |
awk '{print $2}'
end
This gives output similar to the following:
~/temp/hello_world $ ff controller
./app/controllers/application_controller.rb
./config/initializers/application_controller_renderer.rb
~/temp/hello_world $

CVS command to get brief history of repository

I am using following command to get a brief history of the CVS repository.
cvs -d :pserver:*User*:*Password*#*Repo* rlog -N -d "*StartDate* < *EndDate*" *Module*
This works just fine except for one small problem. It lists all tags created on each file in that repository. I want the tag info, but I only want the tags that are created in the date range specified. How do I change this command to do that.
I don't see a way to do that natively with the rlog command. Faced with this problem, I would write a Perl script to parse the output of the command, correlate the tags to the date range that I want and print them.
Another solution would be to parse the ,v files directly, but I haven't found any robust libraries for doing that. I prefer Perl for that type of task, and the parsing modules don't seem to be very high quality.

command line recursive word-based diff?

is there a command line program that gives recursive word-based diff (on 2 directories)?
diff -u is recursive, but it doesn't do word by word comparison. wdiff and dwdiff does word based diff but there are not built-in options for recursive diff.
I would like to pipe the result to colordiff so a program that generates output that colordiff understands would be especially useful. Any suggestions? Thanks!
CC
Git can do it and output color:
The following often works:
git diff --color-words path1 path2
but in general you may need to do
git diff --no-index --color-words path1 path2
Neither file even needs to be in a git repository!
--no-index is needed if you and the paths are in a git working tree. It can be elided if you or one of the files are outside a git working tree.
Manpage: https://git-scm.com/docs/git-diff/1.8.5 (and later...)
git diff --no-index [--options] [--] […​]
This form is to compare the given two paths on the filesystem. You can
omit the --no-index option when running the command in a working tree
controlled by Git and at least one of the paths points outside the
working tree, or when running the command outside a working tree
controlled by Git.

Perforce -- generate a diff including added files?

When I use "p4 diff", it ignores files that I have open for add. Is it possible to generate a diff that includes added files as well as changed files?
Considering the diff in Perforce compare the files in the client workspace to revisions in the depot, the short answer is "no".
There is no recorded history to compare to for the added file (not committed to the depot before a submit)
The longer answer would involve a script to complete the diff with the full content of the added files. (kind of like in this SO question)
This is a known missing feature of p4 diff that lots of tools dealing with Perforce have to work around.
The code review tool Reviewboard comes with the tool post-review. It is used to create diffs for a a codereview, but it will just do a diff if you want.
It's in python, you could pull out the diff section for your own use.
I wrote this to help me on cygwin:
#!/bin/bash
if [ $# -ne 1 ]; then
echo "usage: $0 <pathSpec>"
exit 1
fi
pathSpec=$1
doIt () {
p4 opened "$pathSpec" | egrep "#.* - add" | while read f; do
# figure out the workspace path
depotPath=${f%#*}
clientFileLine=$(p4 fstat "$depotPath" | grep clientFile)
workspacePathWin=${clientFileLine#... clientFile }
# diff output
echo ==== $depotPath#1 - $workspacePathWin ====
workspacePath=$(cygpath "$workspacePathWin")
lineCount=$(wc -l < "$workspacePath")
echo ## -0,0 +1,$lineCount ##
# the actual diff contents
sed -e 's/^/+/' "$workspacePath"
echo
done
}
doIt
I just worked around this issue and got my added files included in a Fisheye pre-commit review.
What I did was copy the edited files' diff hunk descriptor header. This includes one line which lists the depot and local paths - pretty straightforward - and another line with the range information, formatted as described here.
So, I added each appended each file's contents to the diff, each preceded by
==== //path/to/depot/file#1 - /path/to/workspace/file ====
## -1,1 +1,LEN ##
where LEN is the number of lines in the added file.
This worked for me; Your Mileage May Vary.
I just got this to work, branching off Aaron's answer. Instead of
==== //path/to/depot/file#1 - /path/to/workspace/file ====
I used
--- //path/to/file [TIMESTAMP GENERATED BY NORMAL DIFF]
+++ //path/to/file [TIMESTAMP GENERATED BY NORMAL DIFF]
## -1,1 +1,LEN ##
Then make sure to have a + at the beginning of each added line.
Just p4 print the added files (I know, that's not great) - but its definitely one way to go.