408 lines
12 KiB
Markdown
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*
|