I am creating a svn diff patch, however it seems the image files are not getting included. The patch contain similar lines for each image file, as shown below:
Index: crimgeoprofile/code/jquery/css/ui-lightness/images/animated-overlay.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: crimgeoprofile/code/jquery/css/ui-lightness/images/animated-overlay.gif
===================================================================
--- crimgeoprofile/code/jquery/css/ui-lightness/images/animated-overlay.gif (revision 1510040)
+++ crimgeoprofile/code/jquery/css/ui-lightness/images/animated-overlay.gif (working copy)
I am using the following command to create a patch:
svn diff > test.diff
Any suggestions on how I can include image files will be appreciated.
SVN does not support to include binary files in diffs. As a side note: git does support binary files. The resulting patch file looks like this:
diff --git a/bin/windows/SDL_mixer.dll b/bin/windows/SDL_mixer.dll
new file mode 100644
index 0000000000000000000000000000000000000000..f48ee2da696f92b66940b91b52aa53c2
GIT binary patch
literal 160256
zcmd?S4SZD9)i*kmOyYopCrYBxf<%o9l`2uFL_&=TgA|RT7>j7Ev^CX7sg%wregu+E
z26K8G$kPW}+uD|hZFwrKv_*(YAs#UMf~XNJW(<Ug6wVlm;iDl0WbXgJ_BoSD06*UQ
z-h1DBFF(yWXYaMwUVE*z*Is+=k13j2?MQYw94`DHi#Z&%c=BJq{Qc}d<;Xr~#Ovoc
zRu6jXl3M4jZ(VZNLl6HbYtG!qzCU-??5yw3`oRw#^JRVK!K}IdA7nlJgRDunPtThD
So technically it is possible, it just doesn't work with svn. So if you desperately need a patch file including binaries, consider checking out svn using git. It's easy: git svn clone http://path/to/svn. Also works similar with svn://.... You can then create a git diff, and apply that diff to any target. The target does not need to be a git repository. git apply my.patch
With Suversion 1.9 you can use --git flag for include binary content to patch file, for example:
svn diff https://storage/svn/project/trunk --git -c 42 > patch-42.diff
Subversion 1.8 already have --git flag, but ignore binary content with it.
Unfortunately, svn diff does not handle binary data.
Check some of the answers from: subversion diff including new files
In particular: https://stackoverflow.com/a/2255846/9822
The Image files are getting included in your diff as indicated by the lines with --- and +++ but they are included as whole files in the patch - this is due in part the the problem of how to meaningfully display changes in binary data such as images in a text only format - unless you would like pages of hex differences, (such as fc -b a.gif b.gif would produce).
So you are told that the files have changed and it is up to you to decide how you would like to compare them - for image files one of the best comparisons of the significant differences is the human eye - you would not expect a revision control system to be able to tell you "This was a picture of a bald man frowning but now it is a pretty redhead cheerleader smiling" would you?
Related
I want to be able stage specific lines of code that match a pattern (MARKETING_VERSION in my case).
I've got the awk command which will show me the lines that match the pattern MARKETING_VERSION but I don't know how to stage the lines from that result to git.
awk '/MARKETING_VERSION/{print NR}' exampleFile.txt
the result in terminal is
1191
1245
How can I use this result to stage those specific lines in that file to git?
I know you can use git add -p but I want to use this in a shell script so I need a non-interactive version.
TIA
What git add -p <file> does is, very roughly, this:
tmpfile=$(mktemp)
tf2=$(mktemp)
tf3=$(mktemp)
git diff <file> > $tmpfile
while [ -s $tmpfile ]; do
extract first diff hunk from $tmpfile to $tf2 and rest to $tf3
show you $tf2, ask if you want to include this hunk
(with options to edit the hunk, etc); repeat until ready
if you say to *add* the hunk, run git apply --cached $tf2
cat < $tf3 > $tf2
done
rm -f $tmpfile $tf2 $tf3
That is, git add -p uses git apply --cached (a specialized sub-variant of git apply --index that ignores the working tree copy of the file). The key takeaway you need, from the above, is this: There are three versions of the file!
The first one (completely ignored here) is frozen for all time and is in the HEAD commit.
The second one is in Git's index aka staging area. That's used by git diff above as the "old version".
The third one is in your working tree. That's used by git diff above as the "new version".
The patches that Git lets you take or skip are simply the result of comparing the "old" (index) and "new" (working tree) version. If you take some patch, Git updates the in-index copy by applying the patch.
Hence, if there are some set of lines in the working tree version (say, lines 100 through 110 inclusive) that you'd like to use to replace some other set of lines (say, lines 90 through 92 inclusive) in the index version, the way to construct that is:
extract the index version;
scrape out lines 1-89 from the index version; concatenate lines 100-110 from the working tree version; concatenate lines 93-end from the index version, all into a temporary file;
replace the index copy with the temporary file.
To read the index version, use git show or git cat-file -p with the name of the index version of the file. If the file's name is path/to/file, the index version's name is :path/to/file (short for :0:path/to/file: we want the copy in slot zero; there must not be a copy in slots 1, 2, or 3 so that there is a copy in slot 0; you can simply attempt to read it from slot zero, and if that fails, assume the file either isn't in the index, or is conflicted).
Reading the working tree file (some select subset of lines) is left as an exercise, as is the concatenation part, and any error checking you wish to include.
Assuming the final resulting file is in a temporary file named $tf (as a shell variable), to update the index copy, you must first make sure an appropriate blob hash ID exists:
hash=$(git hash-object -w -t blob --path="$path" -- "$tf")
for instance (this assumes you want to run the usual .gitattribute filters, if any, and know that the path is $path). Then, if that goes well, use that hash ID with git update-index:
git update-index --cacheinfo "$mode,$hash,$path"
where $mode is either 100644 or 100755 as appropriate for the file. If you don't want to change the mode, you can read the previous mode with git ls-files --cached or similar. Otherwise, provided core.fileMode is true, read the mode from the working tree copy of the file, to match the behavior of git add: convert "has any executable bit set" to 100755 and "has no executable bit set" to 100644. When core.fileMode is false—use git config --get --type bool core.filemode to read it—git add uses the existing mode for this add-patch case.)
I have a yaml file that has a field data.version which I want to detect changes from main branch.\
The yaml looks something like this:
# ...
data:
version: 1.2.3
# ...
There are more fields which are not relevant for this purpose.
I am writing a GitLab-CI script where I have my current commit checked out.
I am able to see the changes in general by using this command:\
git fetch origin main
git diff origin/main HEAD -- my_yaml_file
But this does not allow me to detect changes to this specific field...
Is there a way to get and parse the original file from main branch?
Note that I am trying to avoid checking out the entire repository on a temp directory just for that purpose :)
You can get a specific version of a file with git show
git show origin/main:my_yaml_file
After that you need to parse the yaml file to get the diff
For example using yq
git show origin/main:my_yaml_file|yq eval ".data.version"
Will give out the value of data.version
I have two (big) files and what I need is to extract changed/added lines only. Is a plain text file (CSV).
Simply return and save a third file with these lines..
UPDATE
I resolved with DiffMerge using the "Show Differences Only" function built in described here.
By the way, I still require a solution that "programmatically" do the same thing but I will create another Question maybe because I need it in a Linux environment.
UPDATE 2
Resolved also with TortoiseGit, see below.
Select two files, and TortoiseGit -> Diff
Create Patch file in TortoiseGitMerge
the unified diff file
UPDATE
For viewing diff only, using "Collapse".
UPDATE 2
If you don't need the context, just set the "Context lines for patches" to zero.
diff --changed-group-format='%<' --unchanged-group-format='' file1 file2
What you are looking for could be as simple as the default unified diff format given by git diff but with context lines stripped. You will still get the location information before every change.
git diff --unified=0 <commit1>:<path/to/file1> <commit2>:<path/to/file2> > <output file>
The files do not have to be versioned under Git, you can just omit the commit reference in that case (or when comparing separate files in same version). For different versions of the same file
git diff --unified=0 <commit1> <commit2> -- <file> > <output file>
My .gitattributes has the following in order to diff the XCode project (which is plain text)
*.pbxproj -crlf -diff -merge
But when I diff, still showing binary file
# git diff MyApp.xcodeproj/project.pbxproj
diff --git a/MyApp.xcodeproj/project.pbxproj b/MyApp.xcodeproj/project.pbxproj
index xxx..xxx xxx
Binary files a/MyApp.xcodeproj/project.pbxproj and b/MyApp.xcodeproj/project.pbxproj differ
My .gitattributes is in the same level of .git folder
Correct. Your .gitattributes is saying to treat the file as binary when it comes to diffing and merging. Take a look at this StackOverflow question, which is awfully similar to yours: Git and pbxproj
We have a large base of code that contains several shared projects, solution files, etc in one directory in SVN. We're migrating to Mercurial. I would like to take this opportunity to reorganize our code into several repositories to make cloning for branching have less overhead. I've already successfully converted our repo from SVN to Mercurial while preserving history. My question: how do I break all the different projects into separate repositories while preserving their history?
Here is an example of what our single repository (OurPlatform) currently looks like:
/OurPlatform
---- Core
---- Core.Tests
---- Database
---- Database.Tests
---- CMS
---- CMS.Tests
---- Product1.Domain
---- Product1.Stresstester
---- Product1.Web
---- Product1.Web.Tests
---- Product2.Domain
---- Product2.Stresstester
---- Product2.Web
---- Product2.Web.Tests
==== Product1.sln
==== Product2.sln
All of those are folders containing VS Projects except for the solution files. Product1.sln and Product2.sln both reference all of the other projects. Ideally, I'd like to take each of those folders, and turn them into separate Hg repos, and also add new repos for each project (they would act as parent repos). Then, If someone was going to work on Product1, they would clone the Product1 repo, which contained Product1.sln and subrepo references to ReferenceAssemblies, Core, Core.Tests, Database, Database.Tests, CMS, and CMS.Tests.
So, it's easy to do this by just hg init'ing in the project directories. But can it be done while preserving history? Or is there a better way to arrange this?
EDIT::::
Thanks to Ry4an's answer, I was able to accomplish my goal. I wanted to share how I did it here for others.
Since we had a lot of separate projects, I wrote a small bash script to automate creating the filemaps and to create the final bat script to actually do the conversion. What wasn't completely apparent from the answer, is that the convert command needs to be run once for each filemap, to produce a separate repository for each project. This script would be placed in the directory above a svn working copy that you have previously converted. I used the working copy since it's file structure best matched what I wanted the final new hg repos to be.
#!/bin/bash
# this requires you to be in: /path/to/svn/working/copy/, and issue: ../filemaplister.sh ./
for filename in *
do
extension=${filename##*.} #$filename|awk -F . '{print $NF}'
if [ "$extension" == "sln" -o "$extension" == "suo" -o "$extension" == "vsmdi" ]; then
base=${filename%.*}
echo "#$base.filemap" >> "$base.filemap"
echo "include $filename" >> "$base.filemap"
echo "C:\Applications\TortoiseHgPortable\hg.exe convert --filemap $base.filemap ../hg-datesort-converted ../hg-separated/$base > $base.convert.output.txt" >> "MASTERGO.convert.bat"
else
echo "#$filename.filemap" >> "$filename.filemap"
echo "include $filename" >> "$filename.filemap"
echo "rename $filename ." >> "$filename.filemap"
echo "C:\Applications\TortoiseHgPortable\hg.exe convert --filemap $filename.filemap ../hg-datesort-converted ../hg-separated/$filename > $filename.convert.output.txt" >> "MASTERGO.convert.bat"
fi
done;
mv *.filemap ../hg-conversion-filemaps/
mv *.convert.bat ../hg-conversion-filemaps/
This script looks at every file in an svn working copy, and depending on the type either creates a new filemap file or appends to an existing one. The if is really just to catch misc visual studio files, and place them into a separate repo. This is meant to be run on bash (cygwin in my case), but running the actual convert command is accomplished through the version of hg shipped with TortoiseHg due to forking/process issues on Windows (gah, I know...).
So you run the MASTERGO.convert.bat file, which looks at your converted hg repo, and creates separate repos using the supplied filemap. After it is complete, there is a folder called hg-separated that contains a folder/repo for each project, as well as a folder/repo for each solution. You then have to manually clone all the projects into a solution repo, and add the clones to the .hgsub file. After committing, an .hgsubstate file is created and you're set to go!
With the example given above, my .hgsub file looks like this for "Product1":
Product1.Domain = /absolute/path/to/Product1.Domain
Product1.Stresstester = /absolute/path/to/Product1.Stresstester
Product1.Web = /absolute/path/to/Product1.Web
Product1.Web.Tests = /absolute/path/to/Product1.Web.Tests
Once I transfer these repos to a central server, I'll be manually changing the paths to be urls.
Also, there is no analog to the initial OurPlatform svn repo, since everything is separated now.
Thanks again!
This can absolutely be done. You'll want to use the hg convert command. Here's the process I'd use:
convert everything to a single hg repository using hg convert with a source type of svn and a dest type of hg (it sounds like you've already done this step)
create a collection of filemap files for use with hg convert's --filemap option
run hg convert with source type hg and dest type hg and the source being the mercurial repo created in step one -- and do it for each of the filemaps you created in step two.
The filemap syntax is shown in the hg help convert output, but here's the gist:
The filemap is a file that allows filtering and remapping of files and
directories. Comment lines start with '#'. Each line can contain one of
the following directives:
include path/to/file
exclude path/to/file
rename from/file to/file
So in your example your filemaps would look like this:
# this is Core.filemap
include Core
rename Core .
Note that if you have an include that the exclusion of everything else is implied. Also that rename line ends in a dot and moves everything up one level.
# this is Core.Tests
include Core.Tests
rename Core.Tests .
and so on.
Once you've created the broken-out repositories for each of the new repos, you can delete the has-everything initial repo created in step one and start setting up your subrepo configuration in .hgsub files.