If you've been alt-tabbing to an admin cmd window to run mklink every time you wanted a symlink on Windows, there's a much cleaner way nobody seems to mention. Two settings, set them once, forget about it.
The reason ln -s in git-bash silently turns into cp by default is two unrelated barriers stacked together:
- Windows non-admins can't create symlinks unless Developer Mode is on.
- MSYS (git-bash's runtime) doesn't even try to create native symlinks without the
MSYS env var set.
Fix the first once with admin, fix the second in your shell profile.
# Run once in admin PowerShell, or use Settings → Update & Security → For developers → Developer Mode
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" `
-Name "AllowDevelopmentWithoutDevLicense" -Value 1 -Type DWord
# In ~/.bashrc
export MSYS=winsymlinks:nativestrict
nativestrict makes failures loud — ln -s errors out instead of silently copying when symlinks aren't supported. Avoid winsymlinks:native (the lenient sibling) — its silent fallback is exactly the trap you're trying to escape. Avoid winsymlinks:lnk entirely; .lnk shortcuts aren't symlinks anything else recognizes.
Open a new git-bash window and verify:
ln -s ~/.bashrc /tmp/test-link
ls -la /tmp/test-link
If the line starts with l, it's a real symlink that git, Linux tools, GNU stow, and your dotfiles install.sh all treat consistently across platforms. If it starts with -, either the env var didn't reach the new shell or Developer Mode didn't actually toggle.
Bonus: Developer Mode also unlocks Windows 11's native sudo command, so you can stop alt-tabbing to admin terminals for quick one-offs entirely.
Your Windows Terminal default tab is opening with admin privileges and you don't remember asking for it. The intuitive guess is the AppCompat Layers registry — that's where ticking "Run as administrator" on a shortcut's compatibility tab gets stored, and it persists across reinstalls. Worth checking, but it's the second place to look for WT.
The first place is settings.json:
{
"commandline": "C:\\Program Files\\Git\\bin\\bash.exe",
"elevate": true,
"guid": "{17c3a2bf-...}",
"name": "Git Bash"
}
WT 1.18+ added elevate as a per-profile flag. When it's true and that profile is also pointed to by defaultProfile, every new window silently opens elevated — no UAC prompt at the tab level because the elevation happened at WT launch. Delete the line, restart WT, done.
If you still want an admin tab on demand, add a second profile with a fresh GUID and a different name (e.g. "Git Bash (Admin)") that keeps elevate: true. You get a dropdown choice and a real UAC prompt when you actually need it, instead of unconditional elevation on every launch.
To rule out the registry side as well:
Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"
Each property name is an exe path; a value containing RUNASADMIN means that program is forced to elevate every launch. To clear one, prefer the GUI — right-click the exe → Properties → Compatibility → uncheck "Run this program as administrator" — over editing the registry by hand.
Two mechanisms, same symptom, different layers. For Windows Terminal specifically, the per-profile setting wins; check it first.
When scripting with Oracle SQLcl, the startup banner (version, copyright, connection info) clamps your output. The -S (silent) flag suppresses all of it:
sql -S user/password@connect_string @script.sql
This gives you clean output suitable for piping or log capture.
For even more control inside the session, pair it with:
set heading off
set feedback off
set pagesize 0
set echo off
-S is the entry-level switch. The set commands handle the rest.