or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-publishing.mdgit-operations.mdindex.mdnpm-operations.mdpackage-manager.mdutilities.mdversion-management.md

git-operations.mddocs/

0

# Git Operations

1

2

Comprehensive git integration for branch validation, tagging, history management, and pushing during the npm publishing workflow.

3

4

## Capabilities

5

6

### Git Information Functions

7

8

Functions for retrieving git repository information and status.

9

10

```javascript { .api }

11

/**

12

* Get the latest git tag in the repository

13

* @returns Promise resolving to the latest tag string

14

*/

15

function latestTag(): Promise<string>;

16

17

/**

18

* Get the git repository root directory

19

* @returns Promise resolving to absolute path of git root

20

*/

21

function root(): Promise<string>;

22

23

/**

24

* Get the name of the current git branch

25

* @returns Promise resolving to current branch name

26

*/

27

function getCurrentBranch(): Promise<string>;

28

29

/**

30

* Get the default branch name (main/master)

31

* @returns Promise resolving to default branch name

32

*/

33

function defaultBranch(): Promise<string>;

34

35

/**

36

* Check if current branch has an upstream

37

* @returns Promise resolving to true if upstream exists

38

*/

39

function hasUpstream(): Promise<boolean>;

40

41

/**

42

* Check if HEAD is in detached state

43

* @returns Promise resolving to true if HEAD is detached

44

*/

45

function isHeadDetached(): Promise<boolean>;

46

```

47

48

**Usage Examples:**

49

50

```javascript

51

import * as git from "np/source/git-util.js";

52

53

// Get repository information

54

const currentBranch = await git.getCurrentBranch();

55

const latestTag = await git.latestTag();

56

const gitRoot = await git.root();

57

58

console.log(`On branch: ${currentBranch}`);

59

console.log(`Latest tag: ${latestTag}`);

60

console.log(`Git root: ${gitRoot}`);

61

62

// Check repository state

63

const hasUpstream = await git.hasUpstream();

64

const isDetached = await git.isHeadDetached();

65

66

if (isDetached) {

67

throw new Error("Cannot publish from detached HEAD");

68

}

69

```

70

71

### Git Validation Functions

72

73

Functions for validating git repository state before publishing.

74

75

```javascript { .api }

76

/**

77

* Verify current branch is the designated release branch

78

* @param releaseBranch - Name of the release branch (e.g., 'main', 'master')

79

* @throws Error if not on release branch

80

*/

81

function verifyCurrentBranchIsReleaseBranch(releaseBranch: string): Promise<void>;

82

83

/**

84

* Verify working tree has no uncommitted changes

85

* @throws Error if working tree is dirty

86

*/

87

function verifyWorkingTreeIsClean(): Promise<void>;

88

89

/**

90

* Verify remote history is clean (no unpushed/unpulled commits)

91

* @throws Error if remote is out of sync

92

*/

93

function verifyRemoteHistoryIsClean(): Promise<void>;

94

95

/**

96

* Verify remote repository is valid and accessible

97

* @throws Error if remote is invalid

98

*/

99

function verifyRemoteIsValid(): Promise<void>;

100

101

/**

102

* Verify git version meets minimum requirements

103

* @throws Error if git version is too old

104

*/

105

function verifyRecentGitVersion(): Promise<void>;

106

107

/**

108

* Verify tag does not exist on remote repository

109

* @param tagName - Name of the tag to check

110

* @throws Error if tag already exists on remote

111

*/

112

function verifyTagDoesNotExistOnRemote(tagName: string): Promise<void>;

113

```

114

115

**Usage Examples:**

116

117

```javascript

118

import * as git from "np/source/git-util.js";

119

120

// Validate repository state before publishing

121

async function validateGitState(releaseBranch = "main") {

122

try {

123

// Check branch

124

await git.verifyCurrentBranchIsReleaseBranch(releaseBranch);

125

126

// Check working tree

127

await git.verifyWorkingTreeIsClean();

128

129

// Check remote sync

130

await git.verifyRemoteHistoryIsClean();

131

132

// Check git version

133

await git.verifyRecentGitVersion();

134

135

console.log("Git validation passed");

136

} catch (error) {

137

console.error(`Git validation failed: ${error.message}`);

138

throw error;

139

}

140

}

141

142

// Check if tag already exists

143

async function checkTagAvailability(version) {

144

const tagName = `v${version}`;

145

try {

146

await git.verifyTagDoesNotExistOnRemote(tagName);

147

console.log(`Tag ${tagName} is available`);

148

} catch (error) {

149

throw new Error(`Tag ${tagName} already exists on remote`);

150

}

151

}

152

```

153

154

### Git Operations Functions

155

156

Functions for performing git operations during the publishing workflow.

157

158

```javascript { .api }

159

/**

160

* Fetch latest changes from remote repository

161

* @returns Promise that resolves when fetch completes

162

*/

163

function fetch(): Promise<void>;

164

165

/**

166

* Push commits and tags to remote with graceful error handling

167

* @param remoteIsOnGitHub - True if remote is hosted on GitHub

168

* @returns Promise resolving to push result object

169

*/

170

function pushGraceful(remoteIsOnGitHub: boolean): Promise<GitPushResult>;

171

172

/**

173

* Delete a git tag locally and remotely

174

* @param tagName - Name of the tag to delete

175

* @returns Promise that resolves when tag is deleted

176

*/

177

function deleteTag(tagName: string): Promise<void>;

178

179

/**

180

* Remove the last commit from current branch

181

* @returns Promise that resolves when commit is removed

182

*/

183

function removeLastCommit(): Promise<void>;

184

```

185

186

**Usage Examples:**

187

188

```javascript

189

import * as git from "np/source/git-util.js";

190

191

// Fetch before validation

192

await git.fetch();

193

194

// Push with error handling

195

const pushResult = await git.pushGraceful(true); // GitHub remote

196

if (pushResult.reason) {

197

console.warn(`Push warning: ${pushResult.reason}`);

198

}

199

200

// Rollback operations

201

async function rollbackRelease(tagName) {

202

try {

203

await git.deleteTag(tagName);

204

await git.removeLastCommit();

205

console.log("Successfully rolled back release");

206

} catch (error) {

207

console.error(`Rollback failed: ${error.message}`);

208

}

209

}

210

```

211

212

### Git History Functions

213

214

Functions for analyzing git history and file changes.

215

216

```javascript { .api }

217

/**

218

* Get files that have changed since the last release

219

* @param rootDirectory - Root directory of the project

220

* @returns Promise resolving to array of changed file paths

221

*/

222

function newFilesSinceLastRelease(rootDirectory: string): Promise<string[]>;

223

224

/**

225

* Read file content from the last release

226

* @param file - Path to the file

227

* @returns Promise resolving to file content from last release

228

*/

229

function readFileFromLastRelease(file: string): Promise<string>;

230

231

/**

232

* Get the previous tag or first commit if no tags exist

233

* @returns Promise resolving to previous tag or commit hash

234

*/

235

function previousTagOrFirstCommit(): Promise<string>;

236

237

/**

238

* Get the latest tag or first commit if no tags exist

239

* @returns Promise resolving to latest tag or commit hash

240

*/

241

function latestTagOrFirstCommit(): Promise<string>;

242

243

/**

244

* Get commit log from a specific revision to HEAD

245

* @param revision - Git revision (tag, commit hash, branch)

246

* @returns Promise resolving to formatted commit log string

247

*/

248

function commitLogFromRevision(revision: string): Promise<string>;

249

```

250

251

**Usage Examples:**

252

253

```javascript

254

import * as git from "np/source/git-util.js";

255

256

// Analyze changes since last release

257

async function analyzeChanges(rootDirectory) {

258

const changedFiles = await git.newFilesSinceLastRelease(rootDirectory);

259

const previousTag = await git.previousTagOrFirstCommit();

260

261

console.log(`Changed files since ${previousTag}:`);

262

changedFiles.forEach(file => console.log(` ${file}`));

263

264

// Get commit history

265

const commits = await git.commitLogFromRevision(previousTag);

266

console.log(`Commits since last release: ${commits.length}`);

267

}

268

269

// Compare file versions

270

async function compareFileVersion(filePath) {

271

try {

272

const lastReleaseContent = await git.readFileFromLastRelease(filePath);

273

const currentContent = require('fs').readFileSync(filePath, 'utf8');

274

275

if (lastReleaseContent !== currentContent) {

276

console.log(`${filePath} has changed since last release`);

277

}

278

} catch (error) {

279

console.log(`${filePath} is a new file`);

280

}

281

}

282

```

283

284

## Git Workflow Integration

285

286

### Pre-publish Validation

287

288

Git validation steps performed before publishing:

289

290

1. **Git Version Check**: Ensure git version ≥ 2.11.0

291

2. **Remote Validation**: Verify remote repository is accessible

292

3. **Branch Validation**: Confirm on correct release branch

293

4. **Working Tree**: Ensure no uncommitted changes

294

5. **Remote Sync**: Verify local and remote are in sync

295

6. **Tag Availability**: Check version tag doesn't exist

296

297

### During Publishing

298

299

Git operations during the publishing workflow:

300

301

1. **Fetch**: Update remote tracking information

302

2. **Version Bump**: Package manager creates version commit and tag

303

3. **Validation**: Verify tag was created successfully

304

4. **Push**: Push commits and tags to remote

305

306

### Post-publish Operations

307

308

Git operations after successful publishing:

309

310

1. **Push Verification**: Confirm push was successful

311

2. **Release Notes**: Generate release notes from commits

312

3. **GitHub Integration**: Create release draft if configured

313

314

### Error Recovery

315

316

Git rollback operations on publishing failure:

317

318

1. **Tag Deletion**: Remove version tag if created

319

2. **Commit Removal**: Remove version bump commit

320

3. **State Restoration**: Return to pre-publish state

321

322

## Configuration

323

324

### Branch Configuration

325

326

Configure release branch behavior:

327

328

```javascript

329

// Default branch detection

330

const branch = await git.defaultBranch(); // 'main' or 'master'

331

332

// Custom branch

333

const options = {

334

branch: 'release',

335

anyBranch: false // Strict branch enforcement

336

};

337

338

// Allow any branch

339

const options = {

340

anyBranch: true // Skip branch validation

341

};

342

```

343

344

### Remote Configuration

345

346

Handle different remote configurations:

347

348

```javascript

349

// GitHub integration

350

const isGitHub = hostedGitInfo.fromUrl(repoUrl)?.type === 'github';

351

await git.pushGraceful(isGitHub);

352

353

// Custom remote handling

354

if (!await git.hasUpstream()) {

355

console.warn('No upstream configured, skipping push');

356

}

357

```

358

359

### Tag Configuration

360

361

Configure git tag behavior:

362

363

```javascript

364

// Tag prefix from package manager

365

const tagPrefix = await getTagVersionPrefix(packageManager);

366

const tagName = `${tagPrefix}${version}`; // e.g., 'v1.2.3'

367

368

// Custom tag message

369

const tagMessage = options.message?.replace('%s', version) || version;

370

```

371

372

## Error Conditions

373

374

### Common Git Errors

375

376

**Branch Errors:**

377

- Not on release branch

378

- Detached HEAD state

379

- Branch doesn't exist

380

381

**Working Tree Errors:**

382

- Uncommitted changes

383

- Untracked files in publish directory

384

- Merge conflicts

385

386

**Remote Errors:**

387

- No remote configured

388

- Remote unreachable

389

- Authentication failures

390

- Push/pull conflicts

391

392

**Tag Errors:**

393

- Tag already exists locally

394

- Tag already exists on remote

395

- Invalid tag format

396

397

### Error Messages

398

399

Git utilities provide detailed error messages:

400

401

```javascript

402

// Branch validation error

403

"Not on release branch. Currently on 'feature-branch', expected 'main'"

404

405

// Working tree error

406

"Working tree is not clean. Uncommitted changes in: package.json, src/index.js"

407

408

// Remote sync error

409

"Remote history has diverged. Run 'git pull' to sync with remote"

410

411

// Tag conflict error

412

"Tag 'v1.2.3' already exists on remote. Use a different version or delete the existing tag"

413

```