SDF + Git Practice Guide
A hands-on practice guide for team collaboration using SDF and Git in VS Code. This guide walks through real-world scenarios with two developers working together.
This guide uses two example developers:
- Developer A (ryandiocean)
- Developer B (luckyocean)
Replace these with your actual team members when practicing.
Prerequisites
Before starting these exercises, ensure you have completed:
- New Employee Onboarding - Git, Node.js, VS Code setup
- Git Workflows - Understanding of branch strategy
Git Flow Overview
This diagram shows how ryandiocean and luckyocean collaborate on the same codebase:
main ─────●─────────────────────────────────────●───────●─── (Production)
│ │ ↑
│ hotfix/NS-999│
│ └───────┘
│
↓
develop ──●────●────●────●────●────●────●────●────●─────── (Integration)
│ ↑ │ ↑ │ ↑
│ │ │ │ │ │
ryandiocean luckyocean │
feature/ feature/ │
NS-123 NS-456 │
│ │ │
└─────────┘ │
↓ │
Both merge bugfix branches
to develop (NS-789, NS-790)
may conflict!
Branch Timeline Example
Two Developer Workflow
| Step | ryandiocean | luckyocean |
|---|---|---|
| 1 | git checkout -b feature/NS-123 | git checkout -b feature/NS-456 |
| 2 | Works on beforeSubmit | Works on afterSubmit |
| 3 | Commits and pushes | Commits and pushes |
| 4 | Merges to develop first ✅ | Pulls develop, then merges ✅ |
| 5 | Both features in develop | No conflict (different functions) |
Practice Project Structure
For these exercises, we'll use a sample SDF project:
suitescript-demo/
├── manifest.xml # SDF project manifest
├── deploy.xml # Deployment configuration
├── suitecloud.config.js # SuiteCloud config
├── package.json # NPM dependencies
├── .gitignore
└── src/
├── FileCabinet/
│ └── SuiteScripts/
│ └── user_event_customer.js
└── Objects/
└── customscript_ue_customer_validation.xml
Scenario 1: Feature Development Without Conflict
Goal: Two developers work on different parts of the same file without creating conflicts.
Flow
ryandiocean luckyocean
│ │
├─ 1. checkout develop │
├─ 2. create feature/NS-123 │
├─ 3. edit beforeSubmit │
├─ 4. commit & push │
├─ 5. merge to develop ✅ │
│ │
│ 6. checkout develop
│ 7. pull (gets A's code)
│ 8. create feature/NS-456
│ 9. edit afterSubmit
│ 10. commit & push
│ 11. merge to develop ✅
Result: No conflict because they edited different functions (beforeSubmit vs afterSubmit).
Developer A: Add Email Validation (NS-123)
# Start from develop
git checkout develop
git pull origin develop
git checkout -b feature/NS-123-email-validation
Edit src/FileCabinet/SuiteScripts/user_event_customer.js - add in beforeSubmit:
// Email validation (NS-123 - Developer A)
var email = customer.getValue({ fieldId: 'email' });
if (email && email.indexOf('@') === -1) {
throw Error('Invalid email format');
}
Validate and commit:
# Validate in VS Code
# Ctrl+Shift+P → SuiteCloud: Validate Project
git add .
git commit -m "[NS-123] Add email validation in beforeSubmit"
git push origin feature/NS-123-email-validation
Test in Sandbox:
| Method | When to Use | How |
|---|---|---|
| Upload File | Quick test, single file only | Right-click file → Upload File to Account |
| Deploy Project | New scripts, XML changes, multiple files | Ctrl+Shift+P → SuiteCloud: Deploy Project |
If you only changed one script file and want to test quickly without deploying the entire project:
- Right-click the
.jsfile in VS Code Explorer - Select "Upload File to Account"
- Choose your Sandbox account
- File uploads instantly to File Cabinet
This is faster than full project deploy but only works for existing scripts (the script deployment record must already exist in NetSuite).
Developer B: Add Phone Logging (NS-456)
# Start from develop (in parallel)
git checkout develop
git pull origin develop
git checkout -b feature/NS-456-phone-logging
Edit src/FileCabinet/SuiteScripts/user_event_customer.js - add in afterSubmit:
// Phone logging (NS-456 - Developer B)
var phone = customer.getValue({ fieldId: 'phone' });
log.audit('Customer Phone', 'Phone: ' + phone);
Validate and commit:
git add .
git commit -m "[NS-456] Add phone logging in afterSubmit"
git push origin feature/NS-456-phone-logging
Merging Both Features (No Conflict)
Since developers modified different functions (beforeSubmit vs afterSubmit), Git can merge automatically.
Developer A merges first:
git checkout develop
git pull origin develop
git merge feature/NS-123-email-validation
git push origin develop
Developer B merges after:
git checkout develop
git pull origin develop
git merge feature/NS-456-phone-logging
git push origin develop
Result: Both features are now in develop without conflicts.
Scenario 2: Creating and Resolving Merge Conflicts
Goal: Intentionally create a conflict to practice resolution.
Flow
ryandiocean luckyocean
│ │
├─ 1. create bugfix/NS-789 ├─ 2. create bugfix/NS-790
├─ 3. edit SAME line ├─ 4. edit SAME line
├─ 5. commit & push (to own branch ✅) ├─ 6. commit & push (to own branch ✅)
├─ 7. checkout develop │
├─ 8. pull develop │
├─ 9. merge NS-789 to develop ✅ │
├─ 10. push develop ✅ │
│ │
│ 11. checkout develop
│ 12. pull develop (gets A's changes)
│ 13. merge NS-790 → CONFLICT!
│ 14. open VS Code, see markers
│ 15. combine both changes
│ 16. validate with SuiteCloud
│ 17. git add → git commit
│ 18. push develop ✅
Each developer pushes to their own branch (bugfix/NS-789 and bugfix/NS-790), not to develop. Push rejection only occurs when pushing to a branch that has commits you don't have locally. The conflict happens during merge (step 13), not during push.
Developer A: Change Log Level (NS-789)
git checkout develop
git pull origin develop
git checkout -b bugfix/NS-789-log-level
Edit afterSubmit - CHANGE log.audit to log.debug:
log.debug('After Submit', 'Customer saved with ID: ' + customerId);
git add .
git commit -m "[NS-789] Change log level to debug"
git push origin bugfix/NS-789-log-level
Developer B: Add Timestamp (NS-790)
git checkout develop
git pull origin develop
git checkout -b bugfix/NS-790-timestamp
Edit the same line in afterSubmit:
log.audit('After Submit', 'Customer saved with ID: ' + customerId + ' at ' + new Date());
git add .
git commit -m "[NS-790] Add timestamp to log"
git push origin bugfix/NS-790-timestamp
The Conflict Occurs
Developer A merges first (success):
git checkout develop
git pull origin develop
git merge bugfix/NS-789-log-level
git push origin develop
Developer B tries to merge (CONFLICT!):
git checkout develop
git pull origin develop
git merge bugfix/NS-790-timestamp
# CONFLICT: Merge conflict in user_event_customer.js
Resolving the Conflict in VS Code
VS Code highlights the conflict:
<<<<<<< HEAD
log.debug('After Submit', 'Customer saved with ID: ' + customerId);
=======
log.audit('After Submit', 'Customer saved with ID: ' + customerId + ' at ' + new Date());
>>>>>>> bugfix/NS-790-timestamp
VS Code buttons above the conflict:
| Button | Action |
|---|---|
Accept Current Change | Keep HEAD version (debug) |
Accept Incoming Change | Keep incoming version (audit + timestamp) |
Accept Both Changes | Include both lines |
Compare Changes | Side-by-side view |
Best resolution - combine both changes:
- Click
Accept Current Change - Manually add the timestamp:
log.debug('After Submit', 'Customer saved with ID: ' + customerId + ' at ' + new Date());
Validate and complete the merge:
# Validate
Ctrl+Shift+P → SuiteCloud: Validate Project
git add .
git commit -m "Merge bugfix/NS-790: Resolved conflict - debug with timestamp"
git push origin develop
Scenario 3: Production Hotfix
Goal: Fix a critical production issue using the hotfix workflow.
Flow
1. Critical bug in Production!
│
▼
2. git checkout main (branch from MAIN, not develop!)
│
▼
3. git checkout -b hotfix/NS-999
│
▼
4. Fix the bug in VS Code
│
▼
5. Validate with SuiteCloud
│
▼
6. Deploy to Production
│
▼
7. Merge hotfix to main → push
│
▼
8. Sync fix to develop ✅
Developer A: Critical Null Check (NS-999)
# Branch from MAIN (not develop!)
git checkout main
git pull origin main
git checkout -b hotfix/NS-999-null-check
Edit afterSubmit - add null check at the beginning:
function afterSubmit(context) {
// Hotfix NS-999 - null check
if (!context.newRecord) {
log.error('After Submit', 'No record found');
return;
}
var customer = context.newRecord;
// ... rest of code
}
Validate:
Ctrl+Shift+P → SuiteCloud: Validate Project
Commit and push:
git add .
git commit -m "[NS-999] HOTFIX: Add null check for context.newRecord"
git push origin hotfix/NS-999-null-check
Deploy to Production:
Ctrl+Shift+P → SuiteCloud: Deploy Project → Select Production
Merge to main AND develop:
# Merge to main
git checkout main
git merge hotfix/NS-999-null-check
git push origin main
# Also sync to develop
git checkout develop
git pull origin develop
git merge main
git push origin develop
Scenario 4: Syncing Changes Made in NetSuite UI
Goal: Import and version control changes made directly in NetSuite's web interface.
Flow
1. Someone edited script in NetSuite UI
│
▼
2. Changes are NOT in Git!
│
▼
3. Create sync branch from develop
│
▼
4. Import Files (Ctrl+Shift+P → SuiteCloud: Import Files)
│
▼
5. Import Objects (Ctrl+Shift+P → SuiteCloud: Import Objects)
│
▼
6. Review changes in VS Code
│
▼
7. Commit → Push → Merge to develop ✅
When to Use This
- Someone edited a script directly in NetSuite
- Custom record was modified via UI
- Workflow was updated in NetSuite
- Any change made outside of SDF deployment
Step-by-Step Process
# Create sync branch
git checkout develop
git pull origin develop
git checkout -b sync/NS-888-import-ui-changes
Import Files from NetSuite:
- Press
Ctrl+Shift+P - Type:
SuiteCloud: Import Files - Select your account
- Navigate to
/SuiteScripts/ - Select the modified file(s)
- Click Import
Import Objects from NetSuite:
- Press
Ctrl+Shift+P - Type:
SuiteCloud: Import Objects - Select your account
- Choose object type (e.g.,
usereventscript) - Select the specific object(s)
- Click Import
Commit and merge:
git add .
git commit -m "[NS-888] Sync changes from NetSuite UI
- Imported updated user_event_customer.js
- Imported customscript_ue_customer_validation.xml"
git push origin sync/NS-888-import-ui-changes
# Merge to develop
git checkout develop
git merge sync/NS-888-import-ui-changes
git push origin develop
Discourage direct NetSuite UI edits. Always prefer SDF deployment for version control. Use sync branches only when UI changes were unavoidable.
VS Code SuiteCloud Quick Reference
Command Palette (Ctrl+Shift+P)
| Action | Command |
|---|---|
| Set up account | SuiteCloud: Set Up Account |
| Deploy entire project | SuiteCloud: Deploy Project |
| Validate project | SuiteCloud: Validate Project |
| Import files from NetSuite | SuiteCloud: Import Files |
| Import objects from NetSuite | SuiteCloud: Import Objects |
| List objects in account | SuiteCloud: List Objects |
| Add dependency references | SuiteCloud: Add Dependency References |
Right-Click Context Menu
Right-click on a file in VS Code Explorer:
| Option | Description |
|---|---|
Deploy to Account | Deploy single file to NetSuite |
Compare with Account | Compare local vs NetSuite version |
Upload File to Account | Upload without full project deploy |
Keyboard Shortcuts
| Action | Shortcut |
|---|---|
| Command Palette | Ctrl+Shift+P |
| Open Terminal | Ctrl+` |
| Source Control Panel | Ctrl+Shift+G |
| File Explorer | Ctrl+Shift+E |
| Search in Files | Ctrl+Shift+F |
| Save File | Ctrl+S |
| Save All Files | Ctrl+K S |
Development Workflow Summary
Release to Production Workflow
# Merge develop to main
git checkout main
git pull origin main
git merge develop
git push origin main
# Deploy to production
Ctrl+Shift+P → SuiteCloud: Deploy Project → Production
# Tag the release
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
Branch Naming Convention
| Type | Format | Example |
|---|---|---|
| Feature | feature/NS-XXX-description | feature/NS-123-email-validation |
| Bugfix | bugfix/NS-XXX-description | bugfix/NS-456-fix-null-error |
| Hotfix | hotfix/NS-XXX-description | hotfix/NS-999-critical-fix |
| Sync | sync/NS-XXX-description | sync/NS-888-import-changes |
Git Flow Diagram
main ─────●─────────────────────────●───────●─── (Production)
│ │ ↑
│ hotfix/NS-999│
│ └───────┘
│
↓
develop ──●────●────●────●────●────●────●─────── (Integration)
│ ↑ │ ↑
│ │ │ │
feature/NS-123 bugfix/NS-790
└────┘ └────┘
Practice Exercises
Exercise 1: No-Conflict Merge
- Developer A creates
feature/test-awith changes tobeforeSubmit - Developer B creates
feature/test-bwith changes toafterSubmit - Both merge to develop without conflicts
Exercise 2: Conflict Resolution
- Developer A creates
bugfix/test-amodifying line 50 - Developer B creates
bugfix/test-bmodifying the same line 50 - Practice resolving the conflict using VS Code merge editor
Exercise 3: Hotfix Flow
- Create a hotfix branch from main
- Fix an issue and deploy to production
- Sync the hotfix back to develop
Exercise 4: Import from NetSuite
- Make a small change to a script in NetSuite UI
- Create a sync branch
- Import the changes using SuiteCloud commands
- Commit and merge to develop
Related Documentation
- Git Workflows - Detailed feature, bugfix, and hotfix workflows
- Managing Merge Conflicts - In-depth conflict resolution
- Deployment Workflow Guide - SDF deployment options
- New Employee Onboarding - Initial setup guide