I wonder if the issue here is the graduate students part more than the Julia part (although obviously the tooling needs work). Maintainability is an art that comes with experience (or proper guidance), and I had to deal in college with a ton of really scary C code from other students (like all the program in the main function with 2000 lines scary). And in the same way in a professional scenario (in a polyglot company with mostly young developers) we had to deal with unmaintainable code in multiple languages, from Python to Scala. Even short scripts that were extremely tricky to reproduce in a more sane approach sometimes.
If my job was just that then I would certainly be heavily burned by it and I wouldn't want to touch the language. But the better solution would be to instead learn the language properly and create a serious guideline that everyone has to follow. If people can't use macros properly (or any of Julia's most powerful features), then every PR with a macro requires a very convincing justification and a review from a more experienced developer. If you're adding a new functionality then you have to be sure there isn't cyclic dependencies with other functionalities, and possibly making it a small independent library instead. And more importantly code is not done until it's properly documented, reviewed and unit tested.
I think that this is very insightful. At least in my experience, maintainable code isn't something that naturally arises. It comes from experience and interest in writing code that will need to be maintained. A lot of students (or academic researchers in general) don't really pay much attention to these things, which is totally understandable given their overall incentive structure.
I'm working with a computer science undergrad at the moment who put multiple full versions of his code to into the Github repository. He didn't use branches, he didn't use pull requests for updates, the diff log is just a new file that is the previous one with changes, all of which sort of defeats the purpose of using source control like git. But, as you say, it's something that takes some guidance and experience to understand. I do find that it makes me lean towards tools that encourage good coding practices by design and which make untying knots easier, which it sounds like Julia might not make super easy (I don't have any production experience with it). Obviously, the practices you laid out definitely help to make sure things don't slip through the cracks, though!
Julia is definitely trickier to control because it's an extremely powerful language. After all you can write even programs that can rewrite itself in it (like Cassette/Zygote, which is more than simply AST manipulation but full IR manipulation), there is no limit to how clever your program can be. But that level of introspection in the future could bring amazing linter capability to the language, that could detect all kind of bad practices as you type (for example type piracy, type instabilities, and possibly enforce customizable policies) which will become important tools as more people aim to use the language in production environments.
And until then the best practices for larger project using Julia's paradigm (Multiple Dispatch, which is by itself not as well understood as OOP or functional) will probably become more largely known. I feel like Julia projects should not grow large not because it's not suitable for large scale projects, but because even large scale Julia projects should emerge from the composition of many small and maintainable Julia projects.
If my job was just that then I would certainly be heavily burned by it and I wouldn't want to touch the language. But the better solution would be to instead learn the language properly and create a serious guideline that everyone has to follow. If people can't use macros properly (or any of Julia's most powerful features), then every PR with a macro requires a very convincing justification and a review from a more experienced developer. If you're adding a new functionality then you have to be sure there isn't cyclic dependencies with other functionalities, and possibly making it a small independent library instead. And more importantly code is not done until it's properly documented, reviewed and unit tested.