Personally, I think LabView is an excellent program for what it is designed to do. Aside from inheriting terrible code, which is a problem in any language, with good practice it is very efficient and quick for putting together all sorts of process control, automation, test, and measurement systems. Like text coding, good practice with LabView exists as well - if you have a scrambled, messy VI then it's really the fault of the coder and not the language. Text-coded languages can get very scrambled as well - the onus is on the programmer to not create unnecessarily messy or obfuscated code.
If you start writing your code with future expansion in mind then it's not difficult at all to create VIs which can grow with the needs of program without becoming cumbersome. Just the same as bad text code can quickly become a mess if you hack it out with a short-term view, only to have it outgrow itself and become unmaintainable. It does mean, however, that you have to take the time to learn LabView, just the same as you have to take the time to learn any language or IDE.
Chances are that if LabView is frustrating your efforts you probably should be using something else to create your program, or at least something else for those components of the program.
For example, if you need to do a lot of string handling - more than is convenient to hack through with LabView's string functions - but you really want or need to use LabView for the meat of your application, then there are many options open to you. You can easily code DLLs in something like C or whatever your favourite language is and then access those functions through LabView's DLL interface. This goes for any sort of high-level or abstract function which is awkward to implement with the basic LabView tools.
This has two big advantages - first you can focus your text coding to simply writing functions or procedures. The task of building the application around your functions becomes non-existent. By blending it with LabView, you gain the second advantage of LabView's quick and powerful UI builder and instrumentation connectivity.
In terms of source control, the biggest thing you can do is to flex LabView's inherent capacity for modularity. While you don't have text tools to help you, for example when trying to sort out unknown inherited code, it does have other very powerful features which, in an abstract way, can do many of the same things. It's probably the easiest language in existence to refactor, which means that, in general, refactoring inherited code can be done WHILE you are learning what it does.
If you go to a data source and break the wire, you instantly see everything that it was connected to, for example. The error list will give you a complete list of everything that broke due to a dependency on that data source and you can straight away work away at creating bundles and clusters to clean up the LabView spaghetti. It even highlights the broken data connections on the back panel so you can trace where everything goes. You can quickly encapsulate things in subVIs if it's clear they are littering the main process with clutter, etc. By the time you've figured out what your code does, it's neat and clean and suddenly re-maintainable.
The big exception to this is if the program used a lot of unnecessary globals. Surprise - globals complicate things in LabView too. In that case, there's nothing to do but curse the schmuck who left you the mess. Still, it's not the end of the world.
I suppose, in short, what I'm trying to say is that LabView is a very different language. If it seems frustrating, it's not because the tools don't exist to do the things you are used to in text coding, but simply that they are often implemented in radically different ways. Grepping code isn't an end unto itself, for example, but only a means to an end - the purpose is to discover links and references throughout the program. While you can't grep LabView code, you can discover links and references - it's just done in an totally different way. Learning curve stuff.