git-userhub 3.0.3 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/git-user.js +14 -2
- package/git-userhub-3.0.4.tgz +0 -0
- package/package.json +9 -2
- package/packages/checksums.txt +6 -0
- package/packages/git-userhub-darwin-arm64/README.md +4 -0
- package/{bin/git-user-darwin-arm64 → packages/git-userhub-darwin-arm64/bin/git-user} +0 -0
- package/packages/git-userhub-darwin-arm64/package.json +19 -0
- package/packages/git-userhub-darwin-x64/README.md +4 -0
- package/{bin/git-user-darwin-amd64 → packages/git-userhub-darwin-x64/bin/git-user} +0 -0
- package/packages/git-userhub-darwin-x64/package.json +19 -0
- package/packages/git-userhub-linux-arm64/README.md +4 -0
- package/{bin/git-user-linux-arm64 → packages/git-userhub-linux-arm64/bin/git-user} +0 -0
- package/packages/git-userhub-linux-arm64/package.json +19 -0
- package/packages/git-userhub-linux-x64/README.md +4 -0
- package/{bin/git-user-linux-amd64 → packages/git-userhub-linux-x64/bin/git-user} +0 -0
- package/packages/git-userhub-linux-x64/package.json +19 -0
- package/packages/git-userhub-windows-x64/README.md +4 -0
- package/{bin/git-user-windows-amd64.exe → packages/git-userhub-windows-x64/bin/git-user.exe} +0 -0
- package/packages/git-userhub-windows-x64/package.json +19 -0
- package/bin/LICENSE +0 -21
- package/bin/README.md +0 -514
- package/test_tar.js +0 -44
package/bin/git-user.js
CHANGED
|
@@ -29,8 +29,20 @@ if (!osName || !archName) {
|
|
|
29
29
|
process.exit(1);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const
|
|
33
|
-
const
|
|
32
|
+
const pkgPlatform = platform === 'win32' ? 'windows' : platform;
|
|
33
|
+
const pkgName = `git-userhub-${pkgPlatform}-${arch}`;
|
|
34
|
+
|
|
35
|
+
let binaryPath;
|
|
36
|
+
try {
|
|
37
|
+
// Find the sub-package directory by resolving its package.json
|
|
38
|
+
const subPkgPath = require.resolve(`${pkgName}/package.json`);
|
|
39
|
+
binaryPath = path.join(path.dirname(subPkgPath), 'bin', `git-user${ext}`);
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.error(`❌ git-user native binary not installed!`);
|
|
42
|
+
console.error(` npm should have installed the optional dependency '${pkgName}'.`);
|
|
43
|
+
console.error(` Please try reinstalling the package.`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
34
46
|
|
|
35
47
|
if (!fs.existsSync(binaryPath)) {
|
|
36
48
|
console.error(`❌ git-user binary not found at ${binaryPath}`);
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-userhub",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"description": "Switch Git accounts in one command. No config editing. No SSH key chaos.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"git-user": "bin/git-user.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"test": "echo \"No tests yet\" && exit 0",
|
|
10
|
-
"
|
|
10
|
+
"release": "node scripts/release.js"
|
|
11
|
+
},
|
|
12
|
+
"optionalDependencies": {
|
|
13
|
+
"git-userhub-darwin-arm64": "3.0.6",
|
|
14
|
+
"git-userhub-darwin-x64": "3.0.6",
|
|
15
|
+
"git-userhub-linux-arm64": "3.0.6",
|
|
16
|
+
"git-userhub-linux-x64": "3.0.6",
|
|
17
|
+
"git-userhub-windows-x64": "3.0.6"
|
|
11
18
|
},
|
|
12
19
|
"devDependencies": {
|
|
13
20
|
"tar": "^7.4.3"
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
228e32fdccc3b553ddcefad445a75548c9df5ca03190879d7050008128449742 git-user_darwin_arm64.tar.gz
|
|
2
|
+
5191fda6093bf66946a53504bb3ef0accf776d74d9b3467e36c9cd2c8d7df1a1 git-user_darwin_x86_64.tar.gz
|
|
3
|
+
e43a1171aeedc8f3bd92ddeb38e2b50fbabe5058c5874874c6295f8ea6ca716e git-user_linux_arm64.tar.gz
|
|
4
|
+
fd97690f902462b0f68ab930dd5e6c63ba33a1d5999851787091cf745fcbec60 git-user_linux_x86_64.tar.gz
|
|
5
|
+
3b5ad0b0bfaeb0f2464b123d764cd5da9db2a3f496676e5d27c2ff8fc6957f75 git-user_windows_arm64.tar.gz
|
|
6
|
+
2a15ecc32d0ae3d419f541477aff8687463cd3ab600807d96ed44ec50ecc7503 git-user_windows_x86_64.tar.gz
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-userhub-darwin-arm64",
|
|
3
|
+
"version": "3.0.6",
|
|
4
|
+
"description": "The darwin arm64 binary for git-userhub",
|
|
5
|
+
"os": [
|
|
6
|
+
"darwin"
|
|
7
|
+
],
|
|
8
|
+
"cpu": [
|
|
9
|
+
"arm64"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"git-user": "bin/git-user"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/divyo-argha/git-user.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT"
|
|
19
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-userhub-darwin-x64",
|
|
3
|
+
"version": "3.0.6",
|
|
4
|
+
"description": "The darwin x64 binary for git-userhub",
|
|
5
|
+
"os": [
|
|
6
|
+
"darwin"
|
|
7
|
+
],
|
|
8
|
+
"cpu": [
|
|
9
|
+
"x64"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"git-user": "bin/git-user"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/divyo-argha/git-user.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT"
|
|
19
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-userhub-linux-arm64",
|
|
3
|
+
"version": "3.0.6",
|
|
4
|
+
"description": "The linux arm64 binary for git-userhub",
|
|
5
|
+
"os": [
|
|
6
|
+
"linux"
|
|
7
|
+
],
|
|
8
|
+
"cpu": [
|
|
9
|
+
"arm64"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"git-user": "bin/git-user"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/divyo-argha/git-user.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT"
|
|
19
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-userhub-linux-x64",
|
|
3
|
+
"version": "3.0.6",
|
|
4
|
+
"description": "The linux x64 binary for git-userhub",
|
|
5
|
+
"os": [
|
|
6
|
+
"linux"
|
|
7
|
+
],
|
|
8
|
+
"cpu": [
|
|
9
|
+
"x64"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"git-user": "bin/git-user"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/divyo-argha/git-user.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT"
|
|
19
|
+
}
|
package/{bin/git-user-windows-amd64.exe → packages/git-userhub-windows-x64/bin/git-user.exe}
RENAMED
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "git-userhub-windows-x64",
|
|
3
|
+
"version": "3.0.6",
|
|
4
|
+
"description": "The win32 x64 binary for git-userhub",
|
|
5
|
+
"os": [
|
|
6
|
+
"win32"
|
|
7
|
+
],
|
|
8
|
+
"cpu": [
|
|
9
|
+
"x64"
|
|
10
|
+
],
|
|
11
|
+
"bin": {
|
|
12
|
+
"git-user": "bin/git-user.exe"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/divyo-argha/git-user.git"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT"
|
|
19
|
+
}
|
package/bin/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Divyo Argha
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/bin/README.md
DELETED
|
@@ -1,514 +0,0 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
<br />
|
|
3
|
-
<img src="img/git-user-logo-clean.png" alt="git-user" width="120" height="120" style="border-radius:26px" />
|
|
4
|
-
<!-- <br /><br /> -->
|
|
5
|
-
<h1>git-user</h1>
|
|
6
|
-
|
|
7
|
-
<p>
|
|
8
|
-
<strong>One command to rule all your Git identities.</strong><br />
|
|
9
|
-
Stop committing as the wrong person. Stop juggling SSH keys. Stop editing config files.
|
|
10
|
-
</p>
|
|
11
|
-
|
|
12
|
-
<p>
|
|
13
|
-
<a href="https://github.com/divyo-argha/git-user/releases"><img src="https://img.shields.io/github/v/release/divyo-argha/git-user?style=flat-square&color=00FFAA&label=latest" alt="Latest Release" /></a>
|
|
14
|
-
<a href="https://github.com/divyo-argha/git-user/releases"><img src="https://img.shields.io/github/downloads/divyo-argha/git-user/total?style=flat-square&color=00FFAA&label=gh%20downloads" alt="GitHub Downloads" /></a>
|
|
15
|
-
<a href="https://www.npmjs.com/package/git-userhub"><img src="https://img.shields.io/npm/v/git-userhub?style=flat-square&color=CB3837&logo=npm&logoColor=white&label=npm" alt="npm" /></a>
|
|
16
|
-
<a href="https://www.npmjs.com/package/git-userhub"><img src="https://img.shields.io/npm/dt/git-userhub?style=flat-square&color=CB3837&logo=npm&logoColor=white&label=total%20downloads" alt="total downloads" /></a>
|
|
17
|
-
<a href="https://github.com/divyo-argha/git-user"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/divyo-argha/git-user/main/badges/total-downloads.json&style=flat-square" alt="Combined Downloads" /></a>
|
|
18
|
-
<a href="https://pkg.go.dev/github.com/divyo-argha/git-user"><img src="https://img.shields.io/badge/Go-1.21+-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go" /></a>
|
|
19
|
-
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-22c55e?style=flat-square" alt="MIT" /></a>
|
|
20
|
-
</p>
|
|
21
|
-
|
|
22
|
-
<p>
|
|
23
|
-
<a href="#-the-problem">The Problem</a> ·
|
|
24
|
-
<a href="#-install">Install</a> ·
|
|
25
|
-
<a href="#-quick-start">Quick Start</a> ·
|
|
26
|
-
<a href="#-why-git-user">Why git-user</a> ·
|
|
27
|
-
<a href="#-features">Features</a> ·
|
|
28
|
-
<a href="#-commands">Commands</a> ·
|
|
29
|
-
<a href="#-security">Security</a> ·
|
|
30
|
-
<a href="#-contributing">Contributing</a>
|
|
31
|
-
</p>
|
|
32
|
-
|
|
33
|
-
<br />
|
|
34
|
-
|
|
35
|
-
<img src="https://img.shields.io/badge/GitHub-supported-181717?style=for-the-badge&logo=github&logoColor=white" alt="GitHub" />
|
|
36
|
-
<img src="https://img.shields.io/badge/GitLab-supported-FC6D26?style=for-the-badge&logo=gitlab&logoColor=white" alt="GitLab" />
|
|
37
|
-
<img src="https://img.shields.io/badge/Bitbucket-supported-0052CC?style=for-the-badge&logo=bitbucket&logoColor=white" alt="Bitbucket" />
|
|
38
|
-
<img src="https://img.shields.io/badge/macOS-supported-000000?style=for-the-badge&logo=apple&logoColor=white" alt="macOS" />
|
|
39
|
-
<img src="https://img.shields.io/badge/Linux-supported-FCC624?style=for-the-badge&logo=linux&logoColor=black" alt="Linux" />
|
|
40
|
-
<img src="https://img.shields.io/badge/Windows-supported-0078D4?style=for-the-badge&logo=windows&logoColor=white" alt="Windows" />
|
|
41
|
-
|
|
42
|
-
<br /><br />
|
|
43
|
-
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## 😤 The Problem
|
|
49
|
-
|
|
50
|
-
You're a developer with multiple lives — work, personal, freelance, open source. Each one has its own Git account, its own SSH key, its own email.
|
|
51
|
-
|
|
52
|
-
And every few weeks, this happens:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
# You just pushed 3 commits to your client's repo.
|
|
56
|
-
# Then you check the author.
|
|
57
|
-
|
|
58
|
-
Author: you@personal.com ← 💀 wrong account. again.
|
|
59
|
-
|
|
60
|
-
# Or your work email leaked onto your public GitHub profile.
|
|
61
|
-
# Or your client can see your personal email in their repo history.
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
You've tried everything:
|
|
65
|
-
|
|
66
|
-
| Attempt | Result |
|
|
67
|
-
|---------|--------|
|
|
68
|
-
| Editing `~/.gitconfig` manually | You forget. Every time. |
|
|
69
|
-
| Per-repo `.git/config` overrides | Works until you clone a new repo |
|
|
70
|
-
| Multiple terminal profiles | Still mix them up |
|
|
71
|
-
| SSH config `Host` aliases | Breaks half your existing remotes |
|
|
72
|
-
| Remembering which key goes where | Not a real solution |
|
|
73
|
-
|
|
74
|
-
**git-user is the permanent fix.** Register your identities once. Switch with one command. Everything — git config, SSH key, remote verification — updates automatically in under a second.
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## 📦 Install
|
|
79
|
-
|
|
80
|
-
<table>
|
|
81
|
-
<tr>
|
|
82
|
-
<td width="33%" valign="top">
|
|
83
|
-
|
|
84
|
-
### One-line
|
|
85
|
-
```bash
|
|
86
|
-
curl -sSfL https://raw.githubusercontent.com/divyo-argha/git-user/main/install.sh | bash
|
|
87
|
-
```
|
|
88
|
-
Restart your terminal. PATH is configured automatically.
|
|
89
|
-
|
|
90
|
-
</td>
|
|
91
|
-
<td width="33%" valign="top">
|
|
92
|
-
|
|
93
|
-
### npm
|
|
94
|
-
```bash
|
|
95
|
-
npm install -g git-userhub
|
|
96
|
-
```
|
|
97
|
-
> Published as `git-userhub` on npm.
|
|
98
|
-
> After install, the command is `git-user`.
|
|
99
|
-
|
|
100
|
-
</td>
|
|
101
|
-
<td width="33%" valign="top">
|
|
102
|
-
|
|
103
|
-
### Go
|
|
104
|
-
```bash
|
|
105
|
-
go install github.com/divyo-argha/git-user@latest
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### Self-update
|
|
109
|
-
```bash
|
|
110
|
-
git-user --update
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
</td>
|
|
114
|
-
</tr>
|
|
115
|
-
</table>
|
|
116
|
-
|
|
117
|
-
**Requirements:**  · ssh-keygen (optional, for SSH key generation)
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## ⚡ Quick Start
|
|
122
|
-
|
|
123
|
-
Two minutes to set up. One second to switch forever after.
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
# Step 1 — register your identities (guided, interactive)
|
|
127
|
-
git-user register # → name: work, email: you@company.com
|
|
128
|
-
git-user register # → name: personal, email: you@gmail.com
|
|
129
|
-
git-user register # → name: client-a, email: you@client.com
|
|
130
|
-
|
|
131
|
-
# Step 2 — switch
|
|
132
|
-
git-user switch work
|
|
133
|
-
|
|
134
|
-
# Step 3 — push. that's it.
|
|
135
|
-
git push # ← commits as you@company.com ✓
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
```bash
|
|
139
|
-
# Create and switch in one command
|
|
140
|
-
git-user switch -c freelance me@freelance.com
|
|
141
|
-
|
|
142
|
-
# Always know who you are
|
|
143
|
-
git-user current
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
## 🏆 Why git-user?
|
|
149
|
-
|
|
150
|
-
There are other tools that try to solve this. Here's how git-user is different:
|
|
151
|
-
|
|
152
|
-
| Feature | git-user | direnv / per-dir config | SSH `Host` aliases | Manual `~/.gitconfig` |
|
|
153
|
-
|---------|:--------:|:----------------------:|:------------------:|:---------------------:|
|
|
154
|
-
| One command to switch everything | ✅ | ❌ | ❌ | ❌ |
|
|
155
|
-
| SSH key managed automatically | ✅ | ❌ | ⚠️ partial | ❌ |
|
|
156
|
-
| Works across all repos, not just one | ✅ | ❌ | ✅ | ✅ |
|
|
157
|
-
| SSH connection verified on switch | ✅ | ❌ | ❌ | ❌ |
|
|
158
|
-
| Clean logout/sign-out to void state | ✅ | ❌ | ❌ | ❌ |
|
|
159
|
-
| Encrypted export/import | ✅ | ❌ | ❌ | ❌ |
|
|
160
|
-
| Pre-commit identity guard | ✅ | ❌ | ❌ | ❌ |
|
|
161
|
-
| Security audit built-in | ✅ | ❌ | ❌ | ❌ |
|
|
162
|
-
| Interactive TUI | ✅ | ❌ | ❌ | ❌ |
|
|
163
|
-
| Shell completions | ✅ | ❌ | ❌ | ❌ |
|
|
164
|
-
| Zero config files to edit manually | ✅ | ❌ | ❌ | ❌ |
|
|
165
|
-
|
|
166
|
-
> **The key difference:** git-user manages the *whole identity* — name, email, SSH key, and passphrase protection — as a single atomic unit. Other approaches only solve part of the problem, leaving you to manually wire the rest.
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## ✨ Features
|
|
171
|
-
|
|
172
|
-
<table>
|
|
173
|
-
<tr>
|
|
174
|
-
<td width="50%" valign="top">
|
|
175
|
-
|
|
176
|
-
### 🔑 Identity Management
|
|
177
|
-
- Register unlimited identities — name, email, SSH key
|
|
178
|
-
- Switch in one command, git config updates instantly
|
|
179
|
-
- `switch -c <name>` — create and switch in one step
|
|
180
|
-
- Edit email without re-registering
|
|
181
|
-
- Remove identities safely, with active-identity guard
|
|
182
|
-
|
|
183
|
-
</td>
|
|
184
|
-
<td width="50%" valign="top">
|
|
185
|
-
|
|
186
|
-
### 🔐 SSH Key Handling
|
|
187
|
-
- Auto-generate ed25519 keys per identity
|
|
188
|
-
- `pubkey` — print active identity's public key (add to GitHub, GitLab, Bitbucket)
|
|
189
|
-
- Bind any existing key to any identity
|
|
190
|
-
- `rekey` rotates keys with automatic backup and rollback
|
|
191
|
-
- `IdentitiesOnly yes` — SSH never leaks the wrong key
|
|
192
|
-
|
|
193
|
-
</td>
|
|
194
|
-
</tr>
|
|
195
|
-
<tr>
|
|
196
|
-
<td width="50%" valign="top">
|
|
197
|
-
|
|
198
|
-
### 🛡️ Security & Passphrases
|
|
199
|
-
- Passphrase-protected keys enforced by default
|
|
200
|
-
- `security` audits every identity: permissions, passphrase, key existence
|
|
201
|
-
- `passphrase` changes passphrase only for the active, unlocked identity
|
|
202
|
-
- All config writes are atomic (temp file + rename) — crash-safe
|
|
203
|
-
- All files stored at `0600` permissions
|
|
204
|
-
|
|
205
|
-
</td>
|
|
206
|
-
<td width="50%" valign="top">
|
|
207
|
-
|
|
208
|
-
### 🔒 Passphrase-Gated Switching
|
|
209
|
-
- Gated switch: switching to a passphrase-protected profile requires entering the passphrase to unlock the SSH key
|
|
210
|
-
- Seamless ssh-agent management: the SSH key is added automatically on switch
|
|
211
|
-
- Security by default: you cannot act as an identity without verifying the passphrase first
|
|
212
|
-
- Clean logout: sign out at any time to clear active user config completely
|
|
213
|
-
|
|
214
|
-
</td>
|
|
215
|
-
</tr>
|
|
216
|
-
<tr>
|
|
217
|
-
<td width="50%" valign="top">
|
|
218
|
-
|
|
219
|
-
### 🚀 Passwordless Push
|
|
220
|
-
- Detects HTTPS remotes on `switch` and offers to convert
|
|
221
|
-
- `fix-remote` converts all remotes HTTPS → SSH instantly
|
|
222
|
-
- Works with GitHub, GitLab, Bitbucket, and any Git host
|
|
223
|
-
|
|
224
|
-
</td>
|
|
225
|
-
<td width="50%" valign="top">
|
|
226
|
-
|
|
227
|
-
### 🖥️ Developer Experience
|
|
228
|
-
- Interactive TUI menu (`git-user tui`)
|
|
229
|
-
- Shell completions for bash, zsh, fish
|
|
230
|
-
- Pre-commit hooks to block wrong-identity commits
|
|
231
|
-
- `doctor` diagnoses your entire setup in one command
|
|
232
|
-
- Encrypted export/import for moving to a new machine
|
|
233
|
-
|
|
234
|
-
</td>
|
|
235
|
-
</tr>
|
|
236
|
-
</table>
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
## 🔄 How It Works
|
|
241
|
-
|
|
242
|
-
### Under the hood — one switch
|
|
243
|
-
|
|
244
|
-
```
|
|
245
|
-
git-user switch work
|
|
246
|
-
│
|
|
247
|
-
▼
|
|
248
|
-
1. Looks up "work" in ~/.git-users/config.json
|
|
249
|
-
2. Sets ~/.gitconfig → user.name, user.email
|
|
250
|
-
3. Sets ~/.gitconfig → core.sshCommand (points to your key)
|
|
251
|
-
4. Verifies SSH connection to GitHub/GitLab/Bitbucket
|
|
252
|
-
5. ✅ Switched to "work" (you@company.com)
|
|
253
|
-
|
|
254
|
-
git push ← just works, every time
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### A real day with multiple accounts
|
|
258
|
-
|
|
259
|
-
```
|
|
260
|
-
9:00 AM — starting work
|
|
261
|
-
──────────────────────────────────────────────────────────
|
|
262
|
-
$ git-user switch work
|
|
263
|
-
✅ Switched to work (you@company.com)
|
|
264
|
-
$ git push ← commits as you@company.com ✓
|
|
265
|
-
|
|
266
|
-
1:00 PM — open source on lunch break
|
|
267
|
-
──────────────────────────────────────────────────────────
|
|
268
|
-
$ git-user switch personal
|
|
269
|
-
✅ Switched to personal (you@gmail.com)
|
|
270
|
-
$ git push ← commits as you@gmail.com ✓
|
|
271
|
-
|
|
272
|
-
5:00 PM — freelance client work
|
|
273
|
-
──────────────────────────────────────────────────────────
|
|
274
|
-
$ git-user switch client-a
|
|
275
|
-
✅ Switched to client-a (you@client-a.com)
|
|
276
|
-
$ git push ← commits as you@client-a.com ✓
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
Each switch: under one second. No config editing. No SSH juggling.
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
|
-
## 🚪 Logout / Void State
|
|
284
|
-
|
|
285
|
-
When you are done with your work or leaving a shared machine, you can sign out to clear your active Git identity completely:
|
|
286
|
-
|
|
287
|
-
```bash
|
|
288
|
-
git-user logout
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
What happens:
|
|
292
|
-
- Unloads the active SSH key from `ssh-agent`
|
|
293
|
-
- Clears the global `user.name` and `user.email` from `~/.gitconfig`
|
|
294
|
-
- Clears `core.sshCommand` from `~/.gitconfig`
|
|
295
|
-
- Puts the terminal into a clean "void" state (no git user configured), preventing accidental commits under your identity by other users.
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## 📋 Commands
|
|
300
|
-
|
|
301
|
-
| Command | Description |
|
|
302
|
-
|---------|-------------|
|
|
303
|
-
| `register` | Create a new identity (guided setup with SSH) |
|
|
304
|
-
| `switch <name>` | Switch to an identity |
|
|
305
|
-
| `switch -c <name> [email]` | Create and switch in one command |
|
|
306
|
-
| `list` | Show all identities |
|
|
307
|
-
| `current` | Show active identity |
|
|
308
|
-
| `remove <name>` | Delete an identity |
|
|
309
|
-
| `edit <name> <email>` | Update email |
|
|
310
|
-
| `bind <name> [--ssh-key <path>]` | Link an SSH key to an identity |
|
|
311
|
-
| `pubkey` | Show the public key of the active identity |
|
|
312
|
-
| `passphrase` | Add or change passphrase for the active, unlocked identity |
|
|
313
|
-
| `rekey <name>` | Rotate SSH key (with rollback safety) |
|
|
314
|
-
| `fix-remote` | Convert HTTPS remotes to SSH |
|
|
315
|
-
| `logout` | Sign out, clearing the active identity and restoring a void state |
|
|
316
|
-
| `security` | Audit all identities for security issues |
|
|
317
|
-
| `export --all` | Export all identities + SSH keys (AES-256 encrypted) |
|
|
318
|
-
| `export <name> [name...]` | Export specific identities |
|
|
319
|
-
| `import <file>` | Import from an encrypted bundle |
|
|
320
|
-
| `doctor` | Run a full health check |
|
|
321
|
-
| `tui` | Interactive menu |
|
|
322
|
-
| `completion <shell>` | Shell completions (bash/zsh/fish) |
|
|
323
|
-
| `hook <install\|uninstall>` | Pre-commit hook to verify identity |
|
|
324
|
-
| `--update` | Update to the latest version |
|
|
325
|
-
| `--version` / `-v` | Show version |
|
|
326
|
-
|
|
327
|
-
**Aliases:** `ls` → `list` · `sw` → `switch` · `rm` → `remove`
|
|
328
|
-
|
|
329
|
-
---
|
|
330
|
-
|
|
331
|
-
## 🛡️ Security
|
|
332
|
-
|
|
333
|
-
<table>
|
|
334
|
-
<tr>
|
|
335
|
-
<td width="50%" valign="top">
|
|
336
|
-
|
|
337
|
-
**What git-user does**
|
|
338
|
-
- Private keys stay on your machine at `0600` permissions
|
|
339
|
-
- Config writes are atomic (temp file + rename) — crash-safe
|
|
340
|
-
- `IdentitiesOnly yes` in SSH config — no key leakage
|
|
341
|
-
- Passphrase protection audited by `security` command
|
|
342
|
-
- Export bundles encrypted with AES-256-GCM, passphrase stretched with scrypt (N=2¹⁷)
|
|
343
|
-
- Passphrases are never passed as CLI arguments — entered directly into the terminal
|
|
344
|
-
- `pubkey` only shows the active identity's key — other identities' keys are never exposed
|
|
345
|
-
|
|
346
|
-
</td>
|
|
347
|
-
<td width="50%" valign="top">
|
|
348
|
-
|
|
349
|
-
**What git-user never does**
|
|
350
|
-
- Never stores passphrases
|
|
351
|
-
- Never sends keys or config anywhere
|
|
352
|
-
- Never modifies your repositories
|
|
353
|
-
- Never overwrites existing identities on import
|
|
354
|
-
- `logout` command cleanly clears all gitconfig references and unloads loaded keys
|
|
355
|
-
|
|
356
|
-
</td>
|
|
357
|
-
</tr>
|
|
358
|
-
</table>
|
|
359
|
-
|
|
360
|
-
### Run a security audit
|
|
361
|
-
|
|
362
|
-
```bash
|
|
363
|
-
git-user security
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
```
|
|
367
|
-
✔ Config file permissions OK (0600)
|
|
368
|
-
|
|
369
|
-
ℹ work (you@company.com)
|
|
370
|
-
✔ Permissions OK: git_work
|
|
371
|
-
✔ Passphrase protected
|
|
372
|
-
|
|
373
|
-
ℹ personal (you@gmail.com)
|
|
374
|
-
✔ Permissions OK: git_personal
|
|
375
|
-
⚠ No passphrase detected
|
|
376
|
-
Fix: ssh-keygen -p -f ~/.ssh/git_personal
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
---
|
|
380
|
-
|
|
381
|
-
## 🚚 Moving to a New Machine
|
|
382
|
-
|
|
383
|
-
```bash
|
|
384
|
-
# On your current machine
|
|
385
|
-
git-user export --all
|
|
386
|
-
# → ~/git-user-export-2026-05-29.bundle (AES-256 encrypted)
|
|
387
|
-
|
|
388
|
-
# Transfer the file, then on the new machine
|
|
389
|
-
git-user import ~/git-user-export-2026-05-29.bundle
|
|
390
|
-
# ✅ Imported: work (you@company.com) → ~/.ssh/git_work
|
|
391
|
-
# ✅ Imported: personal (you@gmail.com) → ~/.ssh/git_personal
|
|
392
|
-
|
|
393
|
-
git-user switch work
|
|
394
|
-
# Ready to push immediately
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
---
|
|
398
|
-
|
|
399
|
-
## 🔧 Troubleshooting
|
|
400
|
-
|
|
401
|
-
```bash
|
|
402
|
-
git-user doctor
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
```
|
|
406
|
-
✅ git installed (2.43.0)
|
|
407
|
-
✅ ssh-keygen available
|
|
408
|
-
✅ Active identity: work (you@company.com)
|
|
409
|
-
✅ SSH key exists at ~/.ssh/git_work
|
|
410
|
-
✅ Key permissions OK (0600)
|
|
411
|
-
✅ GitHub connection verified — Hi alice-corp!
|
|
412
|
-
──────────────────────────────────────────────
|
|
413
|
-
Everything looks good.
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
**Common issues:**
|
|
417
|
-
|
|
418
|
-
| Symptom | Fix |
|
|
419
|
-
|---------|-----|
|
|
420
|
-
| `git-user: command not found` | Restart terminal or `source ~/.zshrc` |
|
|
421
|
-
| SSH verification failed | Key not added to platform yet — run `git-user pubkey` to copy the public key |
|
|
422
|
-
| `Permission denied` during install | Expected — installer needs sudo for `/usr/local/bin` |
|
|
423
|
-
| Git asks for credentials on push | Run `git-user fix-remote` to convert HTTPS → SSH |
|
|
424
|
-
|
|
425
|
-
---
|
|
426
|
-
|
|
427
|
-
## 🐚 Shell Completions
|
|
428
|
-
|
|
429
|
-
```bash
|
|
430
|
-
# Bash
|
|
431
|
-
git-user completion bash | sudo tee /etc/bash_completion.d/git-user
|
|
432
|
-
|
|
433
|
-
# Zsh
|
|
434
|
-
git-user completion zsh > "${fpath[1]}/_git-user"
|
|
435
|
-
|
|
436
|
-
# Fish
|
|
437
|
-
git-user completion fish > ~/.config/fish/completions/git-user.fish
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
```bash
|
|
441
|
-
git-user sw<TAB> # → git-user switch
|
|
442
|
-
git-user switch <TAB> # → work personal client-a
|
|
443
|
-
git-user remove <TAB> # → your identity names
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
---
|
|
447
|
-
|
|
448
|
-
## 🪝 Pre-commit Hooks
|
|
449
|
-
|
|
450
|
-
```bash
|
|
451
|
-
git-user hook install # in any repo where identity matters
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
```bash
|
|
455
|
-
git commit -m "Add feature"
|
|
456
|
-
|
|
457
|
-
# ✖ Identity mismatch!
|
|
458
|
-
# Expected: work (you@company.com)
|
|
459
|
-
# Git config: you@gmail.com
|
|
460
|
-
# Run: git-user switch work
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
---
|
|
464
|
-
|
|
465
|
-
## 📁 What Gets Modified
|
|
466
|
-
|
|
467
|
-
```
|
|
468
|
-
~/.git-users/
|
|
469
|
-
└── config.json ← your identities (names, emails, key paths)
|
|
470
|
-
|
|
471
|
-
~/.gitconfig ← updated on every switch/logout (name, email, sshCommand)
|
|
472
|
-
~/.ssh/git_<name> ← private key (never leaves your machine)
|
|
473
|
-
~/.ssh/git_<name>.pub ← public key (what you add to GitHub/GitLab)
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
Your repositories are never touched. Only global git config changes.
|
|
477
|
-
|
|
478
|
-
---
|
|
479
|
-
|
|
480
|
-
## 🤝 Contributing
|
|
481
|
-
|
|
482
|
-
Issues and pull requests are welcome. If something's broken, open an issue. If something's confusing — even just "I didn't understand what this command does" — that's worth filing too.
|
|
483
|
-
|
|
484
|
-
```bash
|
|
485
|
-
git clone https://github.com/divyo-argha/git-user.git
|
|
486
|
-
cd git-user
|
|
487
|
-
make build # build binary
|
|
488
|
-
make test # run tests
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
492
|
-
|
|
493
|
-
---
|
|
494
|
-
|
|
495
|
-
## 📄 License
|
|
496
|
-
|
|
497
|
-
MIT — see [LICENSE](LICENSE).
|
|
498
|
-
|
|
499
|
-
---
|
|
500
|
-
|
|
501
|
-
<div align="center">
|
|
502
|
-
|
|
503
|
-
**Made for developers who just want their Git to work.**
|
|
504
|
-
|
|
505
|
-
<br />
|
|
506
|
-
|
|
507
|
-
[](https://github.com/divyo-argha/git-user)
|
|
508
|
-
[](https://www.npmjs.com/package/git-userhub)
|
|
509
|
-
|
|
510
|
-
<br />
|
|
511
|
-
|
|
512
|
-
<sub>If git-user saved you from a wrong-account commit, consider giving it a ⭐</sub>
|
|
513
|
-
|
|
514
|
-
</div>
|
package/test_tar.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const crypto = require('crypto');
|
|
3
|
-
const tar = require('tar');
|
|
4
|
-
|
|
5
|
-
const assetName = "git-user_darwin_arm64.tar.gz";
|
|
6
|
-
|
|
7
|
-
async function main() {
|
|
8
|
-
console.log("Creating dummy tar file using node-tar...");
|
|
9
|
-
// create dummy git-user
|
|
10
|
-
fs.writeFileSync('git-user', 'dummy binary');
|
|
11
|
-
fs.writeFileSync('malicious.sh', 'echo bad');
|
|
12
|
-
|
|
13
|
-
await tar.create({
|
|
14
|
-
gzip: true,
|
|
15
|
-
file: assetName,
|
|
16
|
-
}, ['git-user', 'malicious.sh']);
|
|
17
|
-
|
|
18
|
-
console.log("Tar created.");
|
|
19
|
-
|
|
20
|
-
const file = fs.readFileSync(assetName);
|
|
21
|
-
const expectedHash = crypto.createHash('sha256').update(file).digest('hex');
|
|
22
|
-
|
|
23
|
-
fs.unlinkSync('git-user');
|
|
24
|
-
fs.unlinkSync('malicious.sh');
|
|
25
|
-
|
|
26
|
-
console.log("Expected hash:", expectedHash);
|
|
27
|
-
|
|
28
|
-
// Now extract securely
|
|
29
|
-
fs.mkdirSync('bin', { recursive: true });
|
|
30
|
-
|
|
31
|
-
await tar.extract({
|
|
32
|
-
file: assetName,
|
|
33
|
-
cwd: 'bin',
|
|
34
|
-
filter: (p, entry) => {
|
|
35
|
-
console.log('Filtering path:', p, entry.path);
|
|
36
|
-
return p === 'git-user' || p === 'git-user.exe' || p === './git-user' || p === './git-user.exe';
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const binContents = fs.readdirSync('bin');
|
|
41
|
-
console.log("Bin contents:", binContents);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
main().catch(console.error);
|