Reputation: 499
On my server, I host my personal Git remote-side projects (with Gitosis), and I have built a web interface to browse the repositories (something like GitHub).
On the remote-side, you are not allowed to do a lot of stuff, because a working tree is missing, and this is correct: by the way, for a repository explorer, with few commands I can do almost everything.
Except for git blame.
How can I blame a file without a working tree, within the remote-side repository?
Upvotes: 17
Views: 9879
Reputation: 1328752
I'm not able to find where the git docs talk about -- option, by the way this works greatly
Actually, this is necessary because "git blame
" is prepared to take an
ancient odd argument order "blame <path> <rev>
" in addition to the
usual "blame [<rev>] <path>
".
That means, as Git 2.17 (Q2 2018) will explain "git blame HEAD COPYING
" in a bare repository failed to run, while "git blame HEAD -- COPYING
" run just fine.
But from 2.17 on, you won't need '--
' anymore.
See commit 0c668f5 (05 Feb 2018) by Junio C Hamano (gitster
).
(Merged by Junio C Hamano -- gitster
-- in commit 0c668f5, 07 Feb 2018)
blame
: tighten command line parser
An ancient odd argument order "
blame <path> <rev>
" in addition to the usual "blame [<rev>] <path>
" has at least two negative ramifications:
In order to tell these two apart, it checks if the last command line argument names a path in the working tree, using
file_exists()
.
However, "blame <rev> <path>
" is a request to explain each and every line in the contents of<path>
stored in revision<rev>
and does not need to have a working tree version of the file. A check withfile_exists()
is simply wrong.To coerce that mistaken
file_exists()
check to work, the code callssetup_work_tree()
before doing so, because the path it has is relative to the top-level of the project tree.
However, "blame <rev> <path>
" MUST be usable even in a bare repository, and there is no reason for lettingsetup_work_tree()
complain and die with "This operation must be run in a work tree".To correct the former, switch to check if the last token is a revision (and if so, parse arguments using "
blame <path> <rev>
" rule).Correct the latter by getting rid of
setup_work_tree()
andfile_exists()
check--the only case the call to this function matters is when we are running "blame <path>
" (i.e. no starting revision and asking to blame the working tree file at<path>
, digging through theHEAD
revision), but there is a call insetup_scoreboard()
just before it callsfake_working_tree_commit()
.
So in short, starting Git 2.17, this will work in a bare repo:
git blame master -- README.txt
And with Git 2.22, the error message "This operation must be run in a work tree
" should disappear!
"git blame -- path
" in a non-bare repository starts blaming from the working tree, and the same command in a bare repository errors out because there is no working tree by definition.
The command has been taught to instead start blaming from the commit at HEAD,
which is more useful.
See commit a544fb0 (07 Apr 2019) by SZEDER Gábor (szeder
).
(Merged by Junio C Hamano -- gitster
-- in commit d8620d3, 25 Apr 2019)
blame
: default to HEAD in a bare repo when no start commit is given
When '
git blame
' is invoked without specifying the commit to start blaming from, it starts from the given file's state in the work tree.
However, when invoked in a bare repository without a start commit, then there is no work tree state to start from, and it dies with the following error message:$ git rev-parse --is-bare-repository true $ git blame file.c fatal: this operation must be run in a work tree
This is misleading, because it implies that '
git blame
' doesn't work in bare repositories at all, but it does, in fact, work just fine when it is given a commit to start from.We could improve the error message, of course, but let's just default to HEAD in a bare repository instead, as most likely that is what the user wanted anyway (if they wanted to start from an other commit, then they would have specified that in the first place).
'
git annotate
' is just a thin wrapper around 'git blame
', so in the same situation it printed the same misleading error message, and this patch fixes it, too.
Note: if you are using gitweb to see the "blames", as recommended by Jakub Narębski, there is a rather old bug in gitweb, where the incremental blame output in javascript actions mode never worked.
This is fixed with Git 2.24 (Q4 2019).
See commit 52bd3e4 (27 Oct 2019) by Robert Luberda (roblub
).
(Merged by Junio C Hamano -- gitster
-- in commit 0d6799e, 30 Oct 2019)
gitweb
: correctly store previous rev in javascript-actions modeSigned-off-by: Jonathan Nieder
Signed-off-by: Robert Luberda
Acked-by: Jakub Narębski
Without this change, the setting
$feature{'javascript-actions'}{'default'} = [2];
in
gitweb.conf
breaks gitweb's blame page: clicking on line numbers displayed in the second column on the page has no effect.For comparison, with javascript-actions disabled, clicking on line numbers loads the previous version of the line.
Addresses https://bugs.debian.org/741883.
With Git 2.42 (Q3 2023), "git blame --contents=file
"(man) has been taught to work in a bare repository.
See commit 835950b (21 Jul 2023) by Han Young (eseedo
).
(Merged by Junio C Hamano -- gitster
-- in commit f4a7c24, 04 Aug 2023)
blame
: allow--contents
to work with bare repoSigned-off-by: Han Young
The
--contents
option can be used withgit blame
(man) to blame the file as if it had the contents from the specified file.
Since 1a3119e ("blame
: allow--contents
to work with non-HEAD commit", 2023-03-24, Git v2.41.0-rc0 -- merge listed in batch #7), the--contents
option can work with non-HEAD commit.
However, if you try to use--contents
in a bare repository, you get the following error:fatal: this operation must be run in a work tree
This is because before trying to generate a fake working tree commit, we always call
setup_work_tree()
.
But in a bare repo, working tree is not available.
The call tosetup_work_tree
is used to prepare the reading of the blamed file in the working tree, which isn't necessary if we are reading the contents from the specific file instead of the file in the working tree.Add a check in
setup_scoreboard
to skipsetup_work_tree
if we are reading from the file specified in--contents
.This enables us to use
--contents
in a bare repo.
This is a nice addition on top of 1a3119e, having a working tree to use--contents
is optional.Add test for the
--contents
option with bare repo to the annotate-tests.sh test script.
Upvotes: 0
Reputation: 41845
The following should work even in bare repositories:
git blame <rev> -- <path>
E.g.
git blame master -- README.txt
Upvotes: 31