Let's say we have 5 patches for a file, and 4 of the patches changed the file content and add new lines. But we can still apply a single patch 5 to the git tree. Why? Since I thought the line numbers has changed, and so the line contents didn't match any more. How does git determine which line I made a change? Through the three line context of the change? I don't think it is plausible.
BTW, how to generate a number zero patch like [PATCH 0/5]? It seems format patch can only generate from 0001.
Through the three line context of the change?
This is how git apply describes it:
Ensure at least <n> lines of surrounding context match before and after each change.
When fewer lines of surrounding context exist they all must match.
So yes, even if the line numbers changed, the context is still key in determining if a patch should apply or not.
Regarding the numbering aspect, I didn't test, but see if the --start-number option of git format-patch command can help:
--start-number <n>
Start numbering the patches at <n> instead of 1.
Related
I am merging two git branches together. I am using vimdiff to do this, so there are three vim panes shown in my terminal.
This same conflict arises hundreds of times in my merge:
Every time I come across it, I want to do the same thing: keep the top two lines from HEAD (pink) and the bottom line from OTHER (blue).
At the moment I am typing:
diffg 3
To accept blue's changes, then going into insert mode and changing the etc's to var's manually.
I feel like there must be a quicker way to keep the top two lines from pink and the third line from blue every time. Is there? This would save me a lot of typing.
Thanks.
If the conflict is always the same, perhaps, you can use git rerere (What is git-rerere and how does it work?).
If it is not a conflict occurring over different conflicts (like if the conflict is present many times in the file), you can make a macro:
qq
Search for the conflict:
/<<<<<<<
Delete the line:
dd
Find the middle of the conflict:
/=======
Go in line visual mode:
V
Find the line just before the last blue line you want to keep:
/plan-path
Delete all that:
d
Find the end of the conflict:
/>>>>>>>
Delete it
dd
Finally, stop the macro:
q
Once you made the macro, count the number of occurrences of the conflict:
:%s/<<<<<<<//n
Execute the macro as many times:
42#q
If you have other types of conflicts, you can adapt the macro to your needs.
I have fixed some indentation issues in my project and I'm looking at the vimdiff output for the before and after. I notice that vimdiff seems to be very confused as to what the actual changes are, rendering a pretty much useless output in this case:
For example, it seems to think that the very first line is a newly added line:
<div class="text-xs-center p-4">
In reality, all that has changed is the indentation. Vimdiff is not recognizing the changes properly.
In another, similar file, the diff works much better:
I think the difference is that in the second file I did not remove the first line break.
Is there a way to manually fix this sort of thing, so that the diff shows properly? I don't want to change either file, the changes are correct. But I'd like to tell vimdiff that it's comparing the wrong lines to one another.
Is this possible?
The underlying diff tool compares individual lines, regardless of whether "only" indentation changed, or something more fundamental. As in your first case, there's one extra unindented line, so diff recognizes that as unchanged, and this messes up the entire diff.
If you want to ensure that only indentation got changed, you can ignore whitespace changes via
:set diffopt+=iwhite
Then, the diff should show no changes at all (or, in your first example, only the added line 5).
Maybe there are also other diff utilities that more intelligently handle these cases. If you find such tool, you can configure Vim to use it via 'diffexpr'.
example code
diff -r -u -P a.c b.c > diff.patch
I've tried to search in man.
man says that diff -u is to unify the pattern of output, what is the meaning of that and when should we use it?
thanks a lot.
From Wikipedia (diff utility):
The unified format (or unidiff) inherits the technical improvements made by the context format, but produces a smaller diff with old and new text presented immediately adjacent. Unified format is usually invoked using the "-u" command line option. This output is often used as input to the patch program. Many projects specifically request that "diffs" be submitted in the unified format, making unified diff format the most common format for exchange between software developers.
...
The format starts with the same two-line header as the context format, except that the original file is preceded by "---" and the new file is preceded by "+++". Following this are one or more change hunks that contain the line differences in the file. The unchanged, contextual lines are preceded by a space character, addition lines are preceded by a plus sign, and deletion lines are preceded by a minus sign.
A hunk begins with range information and is immediately followed with the line additions, line deletions, and any number of the contextual lines. The range information is surrounded by double-at signs, and combines onto a single line what appears on two lines in the context format (above). The format of the range information line is as follows:
## -l,s +l,s ## optional section heading
...
The idea of any format that diff throws at you is to transform a source file into a destination file following a series of steps. Let's see a simple example of how this works with unified format.
Given the following files:
from.txt
a
b
to.txt
a
c
The output of diff -u from.txt to.txt is:
--- frokm.txt 2015-03-17 04:34:47.076997087 -0430
+++ to.txt 2015-03-17 04:35:27.872996388 -0430
## -1,2 +1,2 ##
a
-b
+c
Explanation. Header description:
--- from.txt 2015-03-17 22:42:18.575039925 -0430 <-- from-file time stamp
+++ to.txt 2015-03-17 22:42:10.495040064 -0430 <-- to-file time stamp
This diff contains just one hunk (only one set of changes to turn file form.txt into to.txt):
## -1,2 +1,2 ## <-- A hunk, a block describing chages between both files, there could be several of these in the diff -u output
^ ^
| (+) means that this change starts at line 1 and involves 2 lines in the to.txt file
(-) means that this change starts at line 1 and involves 2 lines of the from.txt file
Next, the list of changes:
a <-- This line remains the same in both files, so it won't be changed
-b <-- This line has to be removed from the "from.txt" file to transform it into the "to.txt" file
+c <-- This line has to be added to the "from.txt" file to transform it into the "to.txt" file
Here are some StackOverflow answers with really nice info about this subject:
https://stackoverflow.com/a/10950496/1041822
https://stackoverflow.com/a/2530012/1041822
And some other useful documentation:
https://linuxacademy.com/blog/linux/introduction-using-diff-and-patch/
http://www.artima.com/weblogs/viewpost.jsp?thread=164293
The term unified was made up. Better, perhaps would have been to call it "concise".
The point of diff -u is that it is a more concise representation than context diff. Quoting from the original description of Wayne Davison's posting of unidiff to comp.sources.misc (volume 14, 31 Aug 90):
I've created a new context diff format that combines the old and new chunks into
one unified hunk. The result? The unified context diff, or "unidiff."
Posting your patch using a unidiff will usually cut its size down by around
25% (I've seen from 12% to 48%, depending on how many redundant context lines
are removed). Even if the diffs are generated with only 2 lines of context,
the savings still average around 20%.
Keep in mind that *no information is lost* by the conversion process. Only
the redundancy of having multiple identical context lines. [...]
Here are some useful links:
How to read a patch or diff and understand its structure to apply it manually
What is the format of a patch file?
Not useful (and misleading)
2.2.2 Unified Format, which appears to omit attribution.
is there a way to tell git cherry-pick to use the renormalize merge strategy? I'm not sure the -X option is working.
I have a bunch of commits that seem to assume one type of line ending, and I'm trying to apply them to a branch that assumes another. Not having a good time...
So, for completeness, the answer is that the ignore-all-space merge strategy does the job:
git cherry-pick -X ignore-all-space <commit-id>
And that will let you painlessly cherry-pick commits made when the file had, eg, windows line endings onto a version that has unix file endings.
I know this question is significantly old, but adding this answer because this is the first post from googling "git cherry-pick ignore whitespace".
Even though -X ignore-all-space works fine, you have to manually check the commit if the cherry-pick without ignore space option had some conflicts. (or use --no-commit while cherry-picking and git diff --staged to review it)
In some cases, -X ignore-all-space option looks fine, but some indentations are wrong.
For example, suppose you had some merge conflict with leading whitespace while not using ignore-all-space, like this:
Change from theirs, Indent level 1(no conflict with/out whitespace)
<<<<< HEAD
Indent level 0
=====
Indent level 1 without any code change
>>>>> cherry-picked commit
In this case, -X ignore-all-space shows no conflict but the actual commit will look like this:
Change from theirs, indent level 1
Indent level 0
What happened here is they changed logic so the previous code (Indent level 0) should be indented to level 1, but it didn't because you specified ignore-all-space option.
So the tl;dr is:
-X ignore-all-space option also ignores leading whitespaces, which might be troublesome in some situations and languages like Python.
So you have to manually review after using that option, or...
Use -X ignore-space-at-eol instead, and handle leading whitespace conflicts manually.
But don't stop reading, because these options are not the main reason of this problems - the core of this problem is not everyone is sticking to same whitespace rules.
For leading&trailing whitespaces: use linting tools, or IDEs, or whatever to stick to same rules. This is not OS-specific and can be followed if your team puts some effort to making other developers' life easier.
For eol changes: this is OS-specific, but git fortunately supports core.autocrlf and core.eol for multi-platform development enveronment. see git-scm for more details.
I'd like to have any deleted text always go into the numbered registers, but frequently I go to find something I deleted recently in the numbered registers and it's not there because it was less than one line.
Numbered register 1 contains the text deleted by the most recent
delete or change command, unless the command specified another
register or the text is less than one line (the small delete register
is used then). With each successive deletion or change, Vim shifts the
previous contents of register 1 into register 2, 2 into 3, and so
forth, losing the previous contents of register 9.
It's a fairly rare thing, but when it happens, it's really annoying because I have to undo back to the point where I deleted the text, then either delete into a named register or immediately use the deleted text before it's out of register 0 because I delete something else (stray whitespace, bad comment, whatever) on my way to pasting the small text I just deleted.
I'd like the small delete condition not to matter for text entering the numbered registers 1-9. Anyone know of a way to achieve this?
During another such feature request on Reddit, it was found out that there was a bug in Vim that did exactly that when
:set clipboard^=unnamed
That bug has been fixed in Vim 7.3.649. So, if you use an older version, you could still benefit from the bug :-)
If you really think this is useful behavior, you could raise this enhancement request on the vim_dev mailing list, though in general, additional options are frowned upon. Your chances are higher if you can make a compelling argument and also supply a complete patch with documentation and tests.
Check out the Pull Request into the neovim editor:
[RFC] Add an option to use numbered registers for smaller deletions #8169
I've tried to add the smalldel option, which allows you to configure the minimum number of deleted characters to be pushed into the numbered registers "1.."9
The next neovim release after this PR is merged will contain this option.