agmission/Documents/SVN-Guidelines.md

408 lines
12 KiB
Markdown

# SVN Guidelines — AgMission Project
> Reference for daily SVN workflow, branching, merging, and common commands.
> Repo root: `https://svn.agnav.com:8443/svn/AgMission`
---
## Table of Contents
1. [Repository Layout](#sec-1)
2. [Daily Workflow](#sec-2)
3. [Branching](#sec-3)
4. [Keeping a Branch in Sync with Trunk](#sec-4)
5. [Merging a Branch into Trunk (Reintegrate)](#sec-5)
6. [After Reintegrate: Branch Lifecycle](#sec-6)
7. [Resolving Conflicts](#sec-7)
8. [Common Commands Reference](#sec-8)
9. [Best Practices and What to Avoid](#sec-9)
---
<a id="sec-1"></a>
## 1. Repository Layout
```mermaid
graph TD
ROOT["AgMission/ — repo root"]
ROOT --> T["trunk/"]
ROOT --> B["branches/"]
ROOT --> G["tags/"]
T --> DEV["Development/<br/>stable · always deployable"]
B --> SR["satloc-resume/<br/>spent — reintegrated"]
B --> DEA["data-export-api/<br/>active feature branch"]
B --> JI["job-invoicing/<br/>active feature branch"]
G --> R321["release-3.2.1/<br/>immutable snapshot"]
style DEV fill:#c8e6c9,stroke:#388e3c
style SR fill:#ffcdd2,stroke:#c62828
style DEA fill:#fff9c4,stroke:#f9a825
style JI fill:#fff9c4,stroke:#f9a825
style R321 fill:#e1bee7,stroke:#7b1fa2
```
**Rules:**
- `trunk/Development` is always deployable. Never commit broken code directly here.
- Each significant feature or release cycle gets its own branch.
- Tags are read-only snapshots — never commit to a tag.
---
<a id="sec-2"></a>
## 2. Daily Workflow
### Start of day — update your working copy
```bash
# Update the branch you're actively working in
cd /path/to/AgMission/branches/data-export-api
svn update
# Also update trunk if you need to reference it
cd /path/to/AgMission/trunk/Development
svn update
```
### Check what you've changed
```bash
svn status # show all local changes (M=modified, A=added, D=deleted, ?=unversioned)
svn status -q # quiet: versioned changes only (excludes ? files)
svn diff # full diff of all changes
svn diff path/to/file # diff of a specific file
```
### Stage and commit
SVN has no staging area — `svn commit` sends everything marked for change.
```bash
# Commit all pending changes
svn commit -m "Meaningful commit message describing WHAT and WHY"
# Commit specific files only
svn commit file1.js file2.js -m "Fix X in file1 and Y in file2"
```
**Commit message format (recommended):**
```
#<ticket> Short summary (imperative mood)
- Detail line 1
- Detail line 2
```
### End of day — make sure nothing is left uncommitted
```bash
svn status -q # should return nothing if all work is committed
```
---
<a id="sec-3"></a>
## 3. Branching
### Create a new feature branch from trunk
```bash
# Server-side copy — instant, no data transferred
svn copy ^/trunk/Development ^/branches/my-feature \
-m "Create my-feature branch from trunk rXXX"
# Then check it out locally (if your working copy doesn't cover /branches/)
svn update branches/my-feature
```
### Create a release tag
```bash
svn copy ^/trunk/Development ^/tags/release-X.Y.Z \
-m "Tag release X.Y.Z"
```
### Delete a branch (after reintegrate — see §6)
```bash
svn delete ^/branches/my-feature \
-m "Remove spent my-feature branch post-reintegrate"
```
---
<a id="sec-4"></a>
## 4. Keeping a Branch in Sync with Trunk
**Do this regularly** (at least weekly, or whenever trunk has significant commits) to keep the
branch up to date and avoid large conflict batches at reintegrate time.
```bash
# From inside your feature branch working copy
cd branches/my-feature
svn update # make sure WC is current
svn merge ^/trunk/Development # merge trunk changes into branch
# resolve any conflicts (see §7)
svn commit -m "Sync trunk rXXX into my-feature"
```
> ⚠️ **Never use `--record-only` for a routine sync.** `--record-only` skips applying file
> changes and only updates mergeinfo. Use it only to fix mergeinfo bookkeeping gaps caused by
> very old revisions that predate the branch and have no content relevance. Using it incorrectly
> will silently discard real changes from trunk.
---
<a id="sec-5"></a>
## 5. Merging a Branch into Trunk (Reintegrate)
SVN 1.8+ detects reintegration automatically. You do **not** need `--reintegrate`
(deprecated in 1.8, no-op in 1.14).
### Prerequisites
- The branch must have been **fully synced** with trunk (§4) and that sync committed.
- Your trunk working copy must be clean (`svn status -q` returns nothing).
- No local modifications in trunk WC.
```bash
# 1. Sync branch one last time (if there are recent trunk commits)
cd branches/my-feature
svn update
svn merge ^/trunk/Development
svn commit -m "Final trunk sync before reintegrate"
# 2. Switch to trunk and update
cd ../../trunk/Development
svn update
# 3. Run the reintegrate merge
svn merge ^/branches/my-feature
# SVN auto-detects this as reintegrate direction (branch → trunk)
# 4. Review and resolve any conflicts (see §7)
svn status
svn diff
# 5. Syntax-check JS files if applicable
node --check server/path/to/changed.js
# 6. Commit the merge
svn commit -m "Merge my-feature into trunk (reintegrate r1000-rXXX)"
```
### What a reintegrate does
```mermaid
%%{init: {'gitGraph': {'mainBranchName': 'trunk', 'rotateCommitLabel': false}}}%%
gitGraph
commit id: "r999 — branch point"
branch my-feature
checkout my-feature
commit id: "r1001 feature work"
commit id: "r1002 feature work"
checkout trunk
commit id: "r1003 trunk work"
checkout my-feature
merge trunk id: "r1010 sync from trunk"
commit id: "r1050 final feature commit"
checkout trunk
merge my-feature id: "r1051 reintegrate"
```
SVN applies only the revisions from the branch that haven't already been merged to trunk
(tracked via `svn:mergeinfo`). After the reintegrate commit, the branch is **spent** — see §6.
---
<a id="sec-6"></a>
## 6. After Reintegrate: Branch Lifecycle
A reintegrated branch is **spent** — its mergeinfo record says "all revisions merged." Do not
continue developing on it; create a fresh branch from trunk instead.
```mermaid
stateDiagram-v2
direction LR
[*] --> Active : svn copy from trunk
Active --> Active : commit feature work
Active --> Syncing : svn merge trunk (weekly)
Syncing --> Active : conflicts resolved + committed
Active --> Reintegrating : feature complete
Reintegrating --> Spent : merge committed to trunk
Spent --> [*] : tag + svn delete
note right of Syncing
Never use --record-only
for routine syncs
end note
note right of Spent
Always tag before
deleting the branch
end note
```
```bash
# Optional: tag the branch state before deleting
svn copy ^/branches/my-feature ^/tags/my-feature-merged-rXXX \
-m "Tag my-feature before deletion"
# Delete the branch from the repository
svn delete ^/branches/my-feature \
-m "Remove spent my-feature branch post-reintegrate (rXXX)"
# Remove it from your local working copy
svn update # this will remove the local branches/my-feature directory
```
---
<a id="sec-7"></a>
## 7. Resolving Conflicts
### Listing conflicts
```bash
svn status | grep "^C\|^.C" # text conflicts (C) and tree conflicts
```
### Text conflict — manual resolution
```bash
# Edit the file and fix conflict markers (<<<<, ====, >>>>)
# Then mark as resolved
svn resolve --accept working path/to/file.js
```
### Text conflict — accept one side wholesale
```bash
svn resolve --accept mine-full path/to/file # keep your local version
svn resolve --accept theirs-full path/to/file # take incoming version entirely
```
### Tree conflict (directory added/deleted/replaced)
```bash
svn info path/to/dir # read the conflict description
# After deciding what to keep:
svn resolve --accept working path/to/dir # keep local (working copy) state
```
### After resolving all conflicts
```bash
svn status | grep "^C" # should return nothing
svn commit -m "Resolve merge conflicts"
```
---
<a id="sec-8"></a>
## 8. Common Commands Reference
### Information
| Command | What it does |
|---|---|
| `svn info` | Show WC path, URL, revision, last-changed info |
| `svn info ^/branches/my-feature` | Info on a repo path (no checkout needed) |
| `svn log --limit 10` | Last 10 commits on current path |
| `svn log ^/trunk/Development --limit 5` | Last 5 commits on trunk |
| `svn log -v --limit 3` | Commits with list of changed files |
| `svn blame file.js` | Show author/revision per line |
### Status & diff
| Command | What it does |
|---|---|
| `svn status` | All local changes (M, A, D, ?, C) |
| `svn status -q` | Versioned changes only |
| `svn diff` | Full diff of local changes |
| `svn diff -r HEAD` | Diff against HEAD revision |
| `svn diff ^/trunk/Development ^/branches/my-feature` | Diff two repo paths |
### Update & revert
| Command | What it does |
|---|---|
| `svn update` | Bring WC up to latest revision |
| `svn update -r 993` | Update to a specific revision |
| `svn revert file.js` | Discard local changes to one file |
| `svn revert -R .` | Discard ALL local changes recursively |
### Add / remove
| Command | What it does |
|---|---|
| `svn add newfile.js` | Schedule new file for versioning |
| `svn add --force new-dir/` | Add entire new directory |
| `svn delete file.js` | Schedule file for deletion |
| `svn delete ^/branches/old-branch -m "msg"` | Delete repo path directly |
### Merge
| Command | What it does |
|---|---|
| `svn merge ^/trunk/Development` | Sync trunk into current branch (run from branch WC) |
| `svn merge ^/branches/my-feature` | Reintegrate branch into trunk (run from trunk WC) |
| `svn merge ^/trunk/Development --dry-run` | Preview merge without applying |
| `svn merge --record-only ^/trunk/Development` | Fix mergeinfo gaps only — no file changes |
| `svn mergeinfo ^/branches/my-feature` | Show what has/hasn't been merged |
### Copy / branch / tag
| Command | What it does |
|---|---|
| `svn copy ^/trunk/Development ^/branches/new -m "msg"` | Create branch |
| `svn copy ^/trunk/Development ^/tags/v1.0 -m "msg"` | Create tag |
| `svn copy ^/branches/old ^/branches/new -m "msg"` | Copy branch |
---
<a id="sec-9"></a>
## 9. Best Practices and What to Avoid
### ✅ Do
- **Commit often** with small, focused commits and meaningful messages.
- **Sync trunk into your branch regularly** (`svn merge ^/trunk/Development`) — at least weekly.
Early, small syncs are far easier to resolve than one big sync at reintegrate time.
- **Run `svn update` before every commit** to catch conflicts early.
- **Syntax-check JS files** before committing: `node --check path/to/file.js`
- **Use `--dry-run`** on any merge to preview the result before applying.
- **Tag releases** before merging or deleting branches.
- **Delete spent branches** to keep the branch list clean.
- **Keep unversioned files out of the WC** — use `.svnignore` or the global `global-ignores` setting.
### ❌ Avoid
| Mistake | Why | Instead |
|---|---|---|
| Committing directly to trunk | Breaks other developers; trunk must stay stable | Work on a feature branch |
| `--record-only` on a routine sync | Silently skips real trunk changes → content drift | Only use to fix bookkeeping gaps on very old revisions |
| Letting a branch go unsynced for months | Massive conflict blast at reintegrate | Sync from trunk weekly |
| Continuing to develop on a spent (reintegrated) branch | SVN mergeinfo considers all revisions merged; new commits will be missed on next merge | Create a new branch from trunk |
| `svn revert -R .` without a backup | Permanent loss of uncommitted work | Back up modified files first, or stash with a patch: `svn diff > my.patch` |
| Committing secrets/credentials | Irrecoverable from SVN history without admin intervention | Use `.env` files excluded by `svnignore` |
### Saving work-in-progress without committing
SVN has no `git stash`. Use a patch file instead:
```bash
svn diff > /tmp/my-wip.patch # save all local changes
svn revert -R . # clean the WC
# ... do the other work, commit it ...
patch -p0 < /tmp/my-wip.patch # reapply your WIP
```
### Setting up global ignores (one-time, per machine)
Add to `~/.subversion/config` under `[miscellany]`:
```ini
global-ignores = *.o *.so *.log node_modules .env *.swp .DS_Store .specstory
```
---
*Last updated: April 2026 — AgMission / AgNav*