How to get proper diff of merge commit in tig - tig

if i got into tig main view, i get a nice graph of commits and merges. i'd prefer to just look at the merge commits to trunk but unlike with normal commits tig where tig shows the full diff with file contents, on merge commits it just shows a list of changed files in the diff view. How do i get tig to display the file contents diff on merge commits?
commit fb56223ec50cf659a308b3c9979c912881147689
Refs: [master], {origin/master}, {origin/HEAD}, juju-1.21-alpha1-229-gfb56223
Merge: 7e7c95d a017b5a
Author: Juju bot
AuthorDate: Mon Sep 22 01:22:03 2014 +0100
Commit: Juju bot
CommitDate: Mon Sep 22 01:22:03 2014 +0100
Merge pull request #803 from mjs/check-ssh-api-methods-are-allowed-during-upgrade
cmd/juju: ensure that API calls used by "juju ssh" are allowed during upgrades
We recently had a regression where an API call required by "juju ssh" wasn't being allowed by the API server while upgrades are in progress. "juju ssh" is one of the few commands that is supposed to work during upgrades.
The Client used by "juju ssh" is now forced into an interface and this is checked using reflection against what the API server will allow during upgrades. Effectively, the compiler helps to check that the required API methods will be allowed.
http://reviews.vapour.ws/r/64/diff/
apiserver/upgrading_root.go | 20 +++++++++++---------
cmd/juju/ssh.go | 15 +++++++++++----
cmd/juju/ssh_test.go | 24 ++++++++++++++++++++++++
3 files changed, 46 insertions(+), 13 deletions(-)
navigating to the individual files (j/k) in the view, says press 'Enter' to view file diff, but hitting enter gets "Failed to find file diff" err message. ideally i'd just be looking at the combined diff for the merge commit.
[update] i traced through tig with sysdig and it looks like its doing the following which on merge commits won't show the actual diff.
git show --encoding=UTF-8 --pretty=fuller --root --patch-with-stat --show-notes --no-color fb56223ec50cf659a308b3c9979c912881147689 --
i guess what i'm looking for on merge commits then is to parse the parents commits and then do something like the following
git diff 7e7c95d a017b5a
[update] so the diff actually isn't correct here as that diff would be between the two parents, and be more inclusive of changes then the merge itself, the best content rendering of the diff seems to be
git diff fb56223^ fb56223

Turns out this is pretty straightforward via external command integration.
I dropped this into ~/.tigrc:
bind diff 7 !git diff %(commit)^ %(commit)
and now just press 7 for the diff output i'm looking.

You have several options:
put this into your .tigrc
set diff-options = -m
you can set many options in ~/.tigrc, see also the manpage:
man tigrc
or start tig with the option -m
tig -m
Options to tig are passed to the underlying git command. More Info about this also in the manpage:
man tig

Related

How can I get the last merged branch name in git

How can i get the last merged branch name in git from the remote
Tried
git log --first-parent --merges -1 --oneline
But not getting the branch name
Please help
In general, you cannot.
A merge commit may have, as its commit message, text of the form merge branch foo or merge branch foo of someurl, but to read that message, you must obtain the commit from the remote. Even so, there's no guarantee that branch foo exists any more, or that the name means anything if it does exist. Merging really works by commit hash IDs, not by branch names; branch names may evanesce.
If you think you need a branch name here, you are probably doing something wrong. Branch names do make sense here in other version control systems, but in Git, depending on them is unwise.
Here is the command you need to give (change the branch name from origin/master to whichever branch you're checking merges for):
git log --merges origin/master --oneline --grep='^Merge' -1 | grep -oe "[^']*[^']" | sed -n 2p
I had quite a bit of a hard time trying to solve this issue.
I had to get this information for my CircleCi pipeline, and to solve my problem I used the GitHub cli.
Specifically the pr list command: https://cli.github.com/manual/gh_pr_list
The following command gives you all the information of the last PR you merged into main
gh pr list -s merged -B main -L 1
Then you need to manipulate the string and get only the branch name. Which is the text before "MERGED"
I took it splitting the string and taking the penultimate element.

Using git diff to replicate changes in another directory

I have multiple websites structured (simplified) as follows under a single GIT repository:
/
/site-1
/site-1/index.js
/site-1/about.js
/site-1/package.json
/site-1/node_modules(not versioned)
/site-1/package-lock.json(not versioned)
/site-2
/site-2/index.js
/site-2/about.js
/site-2/package.json
/site-2/node_modules(not versioned)
/site-2/package-lock.json(not versioned)
/site-3
/site-3/index.js
/site-3/about.js
/site-3/package.json
/site-3/node_modules(not versioned)
/site-3/package-lock.json(not versioned)
I did some amendments in /site-1/index.js, /site-1/package.json and added a file /site-1/changes.md.
The changes were done in 2 separate git commit in a feature branch called feature/carousel.
I want to apply the same changes in /site-2 and /site-3.
I've tried the following:
git format-patch master -o patches to retrieve the new diff in this feature branch with regards to master branch, but i was unable to apply the diff in /site-2 and /site-3.
diff -ruN site-1 site-2 > PatchFile1 to generate a consolidated diff, but it takes into account files that have been modified in /site-2 as well and its not a generic diff that can be applied directly to /site-3
Any idea how to achieve this?
You can use git apply with the --directory option to apply a patch to another main directory, as explained here:
https://blog.soltysiak.it/en/2017/08/how-to-use-git-patch-system-to-apply-changes-into-another-folder-structure/
First, create a patch file changes.patch based on the changes applied to directory site-1. Then you can do the following:
git apply -p1 --directory='site-2' changes.patch
git apply -p1 --directory='site-3' changes.patch
-p1 removes the site folder from the patch headers, which is the main part that differs between the different directories.
--directory='site-2' will cause the site-2 prefix to be added to each header in the patch

how to use "--no-ff --no-commit" using GitPython while merging?

When i use commandline git merge with --no-ff --no-commit works fine. But using GitPython i am unable to dos.
May be i am not finding a correct documentation or forums for the below equivalent operation using GitPython.
Am i missing any ?
command line:
git merge --no-ff --no-commit "<TAG Name> or <Feature branch>"
GitPython:
print(f"Merging from tag '{input_tag}' into 'master'...")
repo = Repo(constants.git_clone_local_path)
repo.git.checkout('master')
repo.git.pull()
repo.git.merge(f'--no-ff --no-commit {input_tag}')
# repo.git.merge(f'{input_tag}', no_ff=True)
print(repo.git.status())
print('Done')
Python gives below error
cmdline: git merge --no-ff --no-commit test_tag
stderr: 'error: unknown option `no-ff --no-commit test_tag'
usage: git merge [<options>] [<commit>...]
or: git merge --abort
or: git merge --continue
-n do not show a diffstat at the end of the merge
--stat show a diffstat at the end of the merge
--summary (synonym to --stat)
--log[=<n>] add (at most <n>) entries from shortlog to merge commit message
--squash create a single commit instead of doing a merge
--commit perform a commit if the merge succeeds (default)
-e, --edit edit message before committing
--cleanup <mode> how to strip spaces and #comments from message
--ff allow fast-forward (default)
--ff-only abort if fast-forward is not possible
--rerere-autoupdate update the index with reused conflict resolution if possible
--verify-signatures verify that the named commit has a valid GPG signature
-s, --strategy <strategy>
merge strategy to use
-X, --strategy-option <option=value>
option for selected merge strategy
-m, --message <message>
merge commit message (for a non-fast-forward merge)
-F, --file <path> read message from file
-v, --verbose be more verbose
-q, --quiet be more quiet
--abort abort the current in-progress merge
--quit --abort but leave index and working tree alone
--continue continue the current in-progress merge
--allow-unrelated-histories
allow merging unrelated histories
--progress force progress reporting
-S, --gpg-sign[=<key-id>]
GPG sign commit
--overwrite-ignore update ignored files (default)
--signoff add Signed-off-by:
--verify verify commit-msg hook
This should work
git.merge('args', no_ff=True)
replace 'args' by yours arguments like your branch...
I didn't find any links in the documentation. But this code worked for me.
repo = Repo(constants.git_clone_local_path)
repo.git.merge(<source_branch>, no_ff=True, no_commit=True)

Fatal: git was built without support for git-add--interactive (NO_PERL=1)

When I do "git add -i" It pops this error:
fatal: git was built without support for git-add--interactive (NO_PERL=1)
I desperately need help!
With Git 2.25 (Q1 2020, five years later), Perl should no longer be a requirement for git add.
Here, "git add -i" is being rewritten in C.
Warning, since Git 2.37 (Q2 2022), the C rewrite is the default.
See the end of this answer.
See commit 8c15904, commit 3d965c7 (15 Nov 2019), and commit 1daaebc (13 Nov 2019) by Slavica Đukić (slavicaDj).
See commit 68db1cb, commit 76b7432, commit 6348bfb (15 Nov 2019), and commit f83dff6 (13 Nov 2019) by Johannes Schindelin (dscho).
See commit 5e82b9e, commit e4cb659 (13 Nov 2019) by Daniel Ferreira (theiostream).
(Merged by Junio C Hamano -- gitster -- in commit f7998d9, 05 Dec 2019)
built-in add -i: implement the help command
Signed-off-by: Slavica Đukić
Signed-off-by: Johannes Schindelin
This imitates the code to show the help text from the Perl script git-add--interactive.perl in the built-in version.
And:
built-in add -i: show unique prefixes of the commands
Original-patch-by: Slavica Đukić
Helped-by: SZEDER Gábor
Signed-off-by: Johannes Schindelin
Just like in the Perl script git-add--interactive.perl, for each command a unique prefix is determined (if there exists any within the given parameters), and shown in the list, and accepted as a shortcut for the command.
To determine the unique prefixes, as well as to look up the command in question, we use a copy of the list and sort it.
While this might seem like overkill for a single command, it will make much more sense when all the commands are implemented, and when we reuse the same logic to present a list of files to edit, with convenient unique prefixes.
At the start of the development of this patch series, a dedicated data structure was introduced that imitated the Trie that the Perl version implements. However, this was deemed overkill, and we now simply sort the list before determining the length of the unique prefixes by looking at each item's neighbor. As a bonus, we now use the same sorted list to perform a binary search using the user-provided prefix as search key.
add-interactive.c explains:
A "prefix item list" is a list of items that are identified by a string, and a unique prefix (if any) is determined for each item.
At the beginning:
git add -i:Start to implement a built-in version of git add --interactive
Signed-off-by: Johannes Schindelin
Unlike previous conversions to C, where we started with a built-in helper, we start this conversion by adding an interception in the run_add_interactive() function when the new opt-in add.interactive.useBuiltin config knob is turned on (or the corresponding environment variable GIT_TEST_ADD_I_USE_BUILTIN), and calling the new internal API function run_add_i() that is implemented directly in libgit.a.
The whole arc of the conversion can be found in the PRs #170-175 at github.com/gitgitgadget/git.
The "--helper approach" can unfortunately not be used here: on Windows we face the very specific problem that a system() call in Perl seems to close stdin in the parent process when the spawned process consumes even one character from stdin. Which prevents us from implementing the main loop in C and still trying to hand off to the Perl script.
The very real downside of the approach we have to take here is that the test suite won't pass with GIT_TEST_ADD_I_USE_BUILTIN=true until the conversion is complete (the --helper approach would have let it pass, even at each of the incremental conversion steps).
Note: You could see, with Git 2.25, the error message (reported in git-for-windows/git issue 2466):
BUG: pathspec.c:555: PATHSPEC_PREFER_CWD requires arguments
This should be fixed in Git 2.25.2 (March 2020).
See commit 849e43c, commit d660a30 (16 Jan 2020) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit f094074, 30 Jan 2020)
built-in add -i: accept open-ended ranges again
Signed-off-by: Johannes Schindelin
The interactive add command allows selecting multiple files for some of its sub-commands, via unique prefixes, indices or index ranges.
When re-implementing git add -i in C, we even added a code comment talking about ranges with a missing end index, such as 2-, but the code did not actually accept those, as pointed out in a comment of git-for-windows/git issue 2466 by qhill.
As an aside the rewrite of git add --interactive in C broke the ability to select files using an open range e.g. Patch update>> 2- to select all but the first file.
This is related to this issue as attempting this results in the same behaviour as in this issue (i.e. BUG in 2.24.1.windows.2 and immediate exit in 2.25.0.windows.1).
Let's fix this, and add a test case to verify that this stays fixed forever.
With Git 2.26 (Q1 2020), the effort to move "git-add--interactive" to C continues.
See commit c480eeb, commit cee6cb7, commit 52628f9, commit 6610e46, commit 90a6bb9, commit 36bae1d, commit d2a233c (21 Dec 2019) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 9a5315e, 05 Feb 2020)
built-in add -p: prepare for patch modes other than "stage"
Signed-off-by: Johannes Schindelin
The Perl script backing git add -p is used not only for that command, but also for git stash -p, git reset -p and git checkout -p.
In preparation for teaching the C version of git add -p to support also the latter commands, let's abstract away what is "stage" specific into a dedicated data structure describing the differences between the patch modes.
Finally, please note that the Perl version tries to make sure that the diffs are only generated for the modified files.
This is not actually necessary, as the calls to Git's diff machinery already perform that work, and perform it well. This makes it unnecessary to port the FILTER field of the %patch_modes struct, as well as the get_diff_reference() function.
Git 2.37 comes with git add -i in C by default.
If you have any issue, like msys2/MSYS2-packages issue 3066, try the workaround git config --global add.interactive.useBuiltin=false.
That particular issue should be resolved with Git 2.37.1 (Q3 2022): rewrite of "git add -i"(man) in C that appeared in Git 2.25 did not correctly record a removed file to the index, which was fixed.
See commit 4788e8b (28 Jun 2022) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 0f0bc21, 02 Jul 2022)
add --interactive: allow update to stage deleted files
Reported-by: Christoph Reiter
Signed-off-by: Johannes Schindelin
The scripted version of git add -i(man) used git update-index --add --remove``(man), but the built-in version implemented only the --add part.
This fixes https://github.com/msys2/MSYS2-packages/issues/3066
The issue was, while usung an add interactive:
git add -i
fatal: unable to stat 'myfile': No such file or directory
Consequence of add.interactive.useBuiltin:
With Git 2.38 (Q3 2022), fix deadlocks between main Git process and subprocess spawned via the pipe_command() API, that can kill "git add -p"(man) that was reimplemented in C recently.
See commit 716c1f6, commit c6d3cce, commit 14eab81, commit ec4f39b, commit 10f7433 (17 Aug 2022) by Jeff King (peff).
See commit 24b56ae (17 Aug 2022) by René Scharfe (rscharfe).
(Merged by Junio C Hamano -- gitster -- in commit a103ad6, 25 Aug 2022)
pipe_command(): mark stdin descriptor as non-blocking
Signed-off-by: Jeff King
Our pipe_command() helper lets you both write to and read from a child process on its stdin/stdout.
It's supposed to work without deadlocks because we use poll() to check when descriptors are ready for reading or writing.
But there's a bug: if both the data to be written and the data to be read back exceed the pipe buffer, we'll deadlock.
The issue is that the code assumes that if you have, say, a 2MB buffer to write and poll() tells you that the pipe descriptor is ready for writing, that calling:
write(cmd->in, buf, 2*1024*1024);
will do a partial write, filling the pipe buffer and then returning what it did write.
And that is what it would do on a socket, but not for a pipe.
When writing to a pipe, at least on Linux, it will block waiting for the child process to read() more.
And now we have a potential deadlock, because the child may be writing back to us, waiting for us to read() ourselves.
An easy way to trigger this is:
git -c add.interactive.useBuiltin=true \
-c interactive.diffFilter=cat \
checkout -p HEAD~200
The diff against HEAD~200 will be big, and the filter wants to write all of it back to us (obviously this is a dummy filter, but in the real world something like diff-highlight would similarly stream back a big output).
If you set add.interactive.useBuiltin to false, the problem goes away, because now we're not using pipe_command() anymore (instead, that part happens in perl).
But this isn't a bug in the interactive code at all.
It's the underlying pipe_command() code which is broken, and has been all along.
Thanks guys for your comments. I fixed it by removing git and installing it "apt-get install git."
The problem was that the Bitnami-LAMP VM came with a pre-built-git that, I guess, wasn't built with PERL. I checked my PERL version and is fine. Anyways, all is good.

Merging fails in mercurial with "Operation not supported"

I've set up my ~/.hgrc as per https://www.mercurial-scm.org/wiki/MergingWithVim to use vimdiff.
[ui]
merge = vimdiff
[merge-tools]
vimdiff.executable = vim
vimdiff.args = -d $base $local $output $other +close +close
However, when I try to run the actual merge, it just fails out not very helpfully with the following:
bash-3.2$ hg --debug merge
searching for copies back to rev 7
resolving manifests
overwrite None partial False
ancestor 88aaf3a2e10f local 311bb03b96cd+ remote 29bec6ac5dd3
junk: versions differ -> m
preserving junk for resolve of junk
updating: junk 1/1 files (100.00%)
picked tool 'vimdiff' for junk (binary False symlink False)
abort: Operation not supported: /Accounts/rainest/mtest/junk.orig
Any idea why it's doing this?
I've figured it out.
It turns out there's a very specific bug in Python2.6's shutil library that occurs if you're working with NFS mounts on a BSD-like system. More information, and the fix, can be found at http://bugs.python.org/issue7512.
Depending on how you installed it Mercurial usually comes with vimdiff pre-configured for merging. On my machine that's in /etc/mercurial/hgrc.d/mergetools.rc but I imagine it's different in your OSX box.
You might want to check to see if it doesn't already use vimdiff for merging if you remove all of that from your .hgrc.
You can use the command hg showconfig --debug to see all the per-user, per-repo, and system-wide configuration items that are in effect. If you see vimdiff in there after the lines you've added are removed then you might be good to go.

Resources