Gitolite Update Hook exclude a repository - hook

I'm adding a gitolite update hook as a VREF and was wondering if there was a way to apply it to all of the repositories except for the gitolite-admin one.
Having a simpler way rather than listing all of the repositories I want to apply the hook on would be great.
Currently I have:
repo #all
- VREF/update = #all
I was thinking of adding an exception above that one for the gitolite-admin repository.
Something like:
repo gitolite-admin
RW+ VREF/update = #all
repo #all
- VREF/update = #all
Is there a way to get a rule like this to work? Thanks for the help! (I tried this way and it didn't seem to work)

Just for other readers less familiar with VREF (introduced with "g3" or Gitolite V3).
The idea behind VREF rules are:
For every refex starting with VREF/FOO/ in a rule that applies to this user, a call to a program called FOO is triggered.
Note that the program isn't even called if the VREF rule doesn't apply to that user.
This is why one can define an 'update' hook even though the update hook is reserved by gitolite.
A normal update hook expects 3 arguments (ref, old SHA, new SHA).
Any VREF will get those three, followed by at least 4 more. Your 'update' VREF should just ignore the extra args.
fallthru is considering success (ie you won't be denied a git operation on a repo because none of the VREF applied)
If fallthru were to be considered 'failure', you'd be forced to add a "success rule" like this for every vref you used in this repo, in each case listing every user who was not already mentioned in the context of that vref
Considering the update VREF program, you could add a parameter which would allow your update script to recognize it is called in the gitolite-admin context (and should do nothing):
repo gitolite-admin
- VREF/update/donothing = #all
repo #all
- VREF/update = #all

Related

Remove one specific empty git commit with command-line tool

For a nodejs command-line tool I add an empty commit to a repo and then want to remove it later.
Later I have at least 3 commits. The first one is a merge commit, the second one is the empty one I created and the third one is likely one from another now merged repo. Now that my tool has done it's task I want to remove the empty commit.
git rebase --onto emptyCommitID^ emptyCommitID
resulted in: fatal: Does not point to a valid commit 'emptyCommitID^'
(since the ID is the correct one I assume the commit is invalid due to it being empty)
git rebase --keep-base --onto thirdCommit^ headCommit
resulted in fatal: cannot combine '--keep-base' with '--onto'
trying rebase -i HEAD~3 after the tool had done it's main job resulted in:fatal: invalid upstream 'HEAD~3' which might be due to either the empty commit or the merged unrelated histories idk.
I do not want to use git filter-branch --prune-empty, because the tool shall leave other potentially empty commits untouched.
(The tool is for merging repos with unrelated histories. I create the empty commit so that files are staged when merged instead of committed directly which also happens when the --no-commit flag is set in an just initialized repo without prior commits)
maybe it is possible to solve this with git rebase --interactive, but I had the described problem with the invalid upstream and view this as very difficult to implement with a command line tool, mostly using exec to execute it's commands. Do you know a solution?
I think git rebase --onto emptyCommitID^ emptyCommitID should work.
fatal: Does not point to a valid commit 'emptyCommitID^' means that the emptyCommitID has no parent. It contradicts that the second one is the empty one and the first one is its parent.

NodeGit checkout a branch but Get error "HEAD detached at origin/branch"?

I am using nodegit to checkout from clone and Open it to do something.
My code like this:
//repo is a Repository from Clone() or Open()
//branchName is your branch name, of course
repo.getBranch('refs/remotes/origin/' + branchName)
.then(function(reference) {
//checkout branch
return repo.checkoutRef(reference);
});
But after that I cd in to branch directory and typing the command like this
git status
or git branch
It's show a red line like this
HEAD detached at origin/branchname
How can I solved it?
Thanks
In general,1 origin/somebranch is not a branch name, and therefore git checkout origin/somebranch results in a detached HEAD, exactly as you are seeing.
Branch names, in Git, don't really do any good, to a first approximation.2 So there's no need to use them. To understand how and why this is the case, let's note that in Git, there are many kinds of names.
A branch name is simply a name which, when spelled out in full, begins with refs/heads/. The branch names master or main, for instance, are really refs/heads/master and refs/heads/main, correspondingly.
A tag name is a name which, when spelled out in full, begins with refs/tags/. So v2.1 is really refs/tags/v2.1.
Git calls these things—these names in general, before they're split into some particular classification—refs or references. Each reference holds one (1) hash ID. The hash ID is what really matters to Git. That's what Git needs. That's what git checkout requires: a hash ID. You can give it any valid commit hash ID, and it will check out that commit.
Hash IDs, though, are big and ugly and look random (though they're not). They are thoroughly unmemorable. What commit is 225365fb5195e804274ab569ac3cc4919451dc7f anyway? If I say v2.31.0-rc0, that probably means something—or at least, seems suggestive of something—to you; but if I say 2253blah you have probably forgotten the 2253 part long before I get to the dc7f part. So refs are for humans. They're not for Git, which only really cares about the hash IDs.
You only need a ref—such as a branch name—if you're a human. If you're a build system, a hash ID is fine. If you're writing part of a build system, just use a hash ID. If you're writing something for a human to use ... well, humans are hard.
Git has a special thing it calls "DWIM", or Do What I Mean, mode. If you run:
git checkout foobranch
and there is no branch named foobranch right now, Git will assume that you mean: Find me a name that resembles foobranch, such as origin/foobranch. Then use that name to make a branch name for me. You can disable this with git checkout --no-guess and sometimes that's a good idea. But sometimes this DWIM mode is exactly what you want.
Note, however, that if the pesky human went and made his own foobranch earlier, not related to origin/foobranch, this git checkout foobranch will get his foobranch, not related to origin/foobranch. So be careful: humans are tricky and weird. They do illogical, unexpected things.
Now, there's a reason humans often want to use a branch name, rather than any other name that results in the detached-HEAD mode. The primary reason they like this is because then, if they make a new commit, Git will change the hash ID stored in the branch name. The new commit will automatically link, backwards, to whatever commit was the one stored in the reference. Then Git will update the branch name so that it now stores the hash ID of the new commit.
This feature is exclusive to branch names. No other kind of name has this special feature. You can select detached-HEAD mode when using a branch name, by running git checkout --detach foobranch for instance. But the default is that when you use git checkout with a branch name—even one that DWIM mode is going to have to create—Git will instead go into attached HEAD mode.3 So that's why humans like branch names, and that's what Git does with them, that it doesn't do with any other reference name.
If you need to accommodate humans, you can do that by letting the DWIM mode do its thing here. That won't satisfy all humans, so watch out. It also won't work in some cases, so watch out. The detached-HEAD mode always works, though.
In NodeGit specifically, you have Branch.create as an async class method of Branch.. You also have Branch.lookup. You could use this to look up a remote-tracking name, like origin/branchname, and use that to create a new local branch, if that's your goal. But as before, watch out for all these various edge cases.
1It is possible to make a (local) branch named origin/somebranch, so that it is a branch name. The result is very confusing unless you carefully call out all names using their full spellings. Don't do this!
2Of course, they do do some good, so the first approximation is pretty rough.
3Git does not call it this, but what else could the right phrase for "opposite of detached HEAD" mode be?

Checking comments in code for messages before committing with Git

If often find myself writing out helpful messages in my code when developing locally. See this code snippet as a simple example:
# Public API
namespace :api do
namespace :v1 do
# REMOVE THE FIRST LINE WHEN DONE TESTING
get :delivery_report, to: 'delivery_report#index'
post :delivery_report, to: 'delivery_report#index'
end
end
The point here is that when I am done and I feel like I can finally commit my work I need to remember that I have to remove the line get :delivery_report, to: 'delivery_report#index'
Is it somehow possible to tell git that before accepting a commit or maybe before staging it, it should warn me about a line in my code that has some content? In this case that would be my comment or any other pre-defined line.
Git supports a "pre-commit hook", in which you can test what the user has proposed committing, and force the commit to fail if some condition(s) apply.
See git pre-commit hook code formatting with partial commit? and How do I properly git stash/pop in pre-commit hooks to get a clean working tree for tests?

Gitolite: calling VREF for all but one repo

I have the following setup. I want to check that commits have a certain commit message format (line limit, etc.). I want this for all repos, but one or two.
How can I tell this gitolite without having to define a group #check_msg that contains most repos. This would be cumbersome...
In my BADCOMMIT VREF, I already included some lines to not check the message if it is called with NOCHECK.
Any ideas??
repo testing
RW+ = #all
? VREF/BADCOMMIT/NOCHECK = #all
repo #all
- VREF/BADCOMMIT = #all
repo gitolite-admin
RW...
Instead of using git notes, I suggest you do this:
repo testing
RW+ = #all
option badcommit.nocheck = 1
repo #all
- VREF/BADCOMMIT = #all
Then, at the start of the VREF, you say
gitolite git-config -q $GL_REPO gitolite-options.badcommit.nocheck && exit 0
Much cleaner, and the knowledge of the exceptions stays within gitolite.conf.
(Assuming v3 of course).
Considering:
that a VREF has no idea of the git repo name or path it is called from, adding:
fallthrough means success (which means, as matt comments, that it will check all the VREFS)
The only solution seems for the VREF script "BADCOMMIT" to somehow detects it is in a git repo it should not test.
If, by convention, said git repo were to contain a **git notes (**which you can add at any time, without changing the git history, see man git notes) with a certain title on this note, it could decide to not go on with its check.
Since there are few git repos which shouldn't be tested with BADCOMMIT, you could add a note to the first commit of that repo.
That way, you don't need a NOCHECK, and you don't need to stop after a certain rule.

Layering projects on top of each other with git

Let there be:
There are different repositories repoA, repoB and repoC each respecting the same directory layout principles, which are to be merged onto a third repoM's working directory (the "master" project).
repoM has an atypical setup (--work-dir and --git-dir are sepparate). repo[A-C] are cloned as bare, and they are set as core.bare = false and core.worktree=<--work-dir-of-repoM>.
The requirements:
I need to always have an overview over the history of all files in repoM's work-dir, which could have stemmed from repo[A-C]. With this approach, I lose all that information.
Alternative:
I've been thinking about using git-subtree instead (git version 1.7.11.2, so it's already built-in), leaving repo[A-C] bare, and then
git pull -s subtree, or
git subtree ...
With the subtree pull strategy, I lose the history on a merge conflict (git blame says so).
I've never used subtree before, but from my understanding it's not possible to merge files from repo[A-C] into repoM's work-dir, those files must be put into a subdirectory of repo[A-C]. This is definitely not what I need. Why? Because of the following ...
Problem statement:
You have different git repositories each containing different sets of files, usually configuration files and some shell scripts. You want to put everything in the $HOME (which is <--work-dir-of-repoM>) directory from all those repositories. You should be able to see at all time where each file comes from, edit, commit and push changes to each one's origin. You've guessed it, it something like vundle, but generalized for any kind of configuration of any program, not just vim bundles. If a conflict occures, one should be able to track down which two authors of the same file need to get in touch with each other and make up a deal (if one needs to be made).
This is for an open-source project I'm trying to get a prototype working, so any help is highly appreciated. Also ideas about already existing projects which do this in a similar manner are highly appreciated.
Note: the "master directory" does not necessarily have to be $HOME, I've used it as a possible hint on the kind of problem this could solve.
Why not simply use Git Submodules in your "master project"?

Resources