Skip to content

Commit 7f8721e

Browse files
authored
Merge pull request #447 from remotemobprogramming/discard-uncommitted-changes
#446 mob start --discard-uncommitted-changes
2 parents c17f133 + d2433c8 commit 7f8721e

File tree

5 files changed

+139
-52
lines changed

5 files changed

+139
-52
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 5.3.0
2+
- Feature: `mob start --discard-uncommitted-changes` allows to discard uncommitted changes and then starting a new mob session
3+
4+
Thank you @stefanscheidt for this feature request
5+
16
# 5.2.0
27
- Feature: `mob done` now pulls when someone else already did `done`
38

configuration/configuration.go

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ const (
1515
SquashWip = "squash-wip"
1616
)
1717

18+
const (
19+
IncludeChanges = "include-changes"
20+
DiscardChanges = "discard-changes"
21+
FailWithError = "fail-with-error"
22+
)
23+
1824
type Configuration struct {
1925
CliName string // override with MOB_CLI_NAME
2026
RemoteName string // override with MOB_REMOTE_NAME
@@ -28,7 +34,7 @@ type Configuration struct {
2834
NotifyCommand string // override with MOB_NOTIFY_COMMAND
2935
NotifyMessage string // override with MOB_NOTIFY_MESSAGE
3036
NextStay bool // override with MOB_NEXT_STAY
31-
StartIncludeUncommittedChanges bool
37+
HandleUncommittedChanges string
3238
StartCreate bool // override with MOB_START_CREATE variable
3339
StartJoin bool
3440
StashName string // override with MOB_STASH_NAME
@@ -118,8 +124,10 @@ func ParseArgs(args []string, configuration Configuration) (command string, para
118124
for i := 1; i < len(args); i++ {
119125
arg := args[i]
120126
switch arg {
127+
case "--discard-uncommitted-changes", "-d":
128+
newConfiguration.HandleUncommittedChanges = DiscardChanges
121129
case "--include-uncommitted-changes", "-i":
122-
newConfiguration.StartIncludeUncommittedChanges = true
130+
newConfiguration.HandleUncommittedChanges = IncludeChanges
123131
case "--debug":
124132
// ignore this, already parsed
125133
case "--stay", "-s":
@@ -181,32 +189,32 @@ func GetDefaultConfiguration() Configuration {
181189

182190
}
183191
return Configuration{
184-
CliName: "mob",
185-
RemoteName: "origin",
186-
WipCommitMessage: "mob next [ci-skip] [ci skip] [skip ci]",
187-
StartCommitMessage: "mob start [ci-skip] [ci skip] [skip ci]",
188-
SkipCiPushOptionEnabled: true,
189-
GitHooksEnabled: false,
190-
VoiceCommand: voiceCommand,
191-
VoiceMessage: "mob next",
192-
NotifyCommand: notifyCommand,
193-
NotifyMessage: "mob next",
194-
NextStay: true,
195-
RequireCommitMessage: false,
196-
StartIncludeUncommittedChanges: false,
197-
StartCreate: false,
198-
WipBranchQualifier: "",
199-
WipBranchQualifierSeparator: "-",
200-
DoneSquash: Squash,
201-
OpenCommand: "",
202-
Timer: "",
203-
TimerLocal: true,
204-
TimerRoom: "",
205-
TimerUser: "",
206-
TimerUrl: "https://timer.mob.sh/",
207-
WipBranchPrefix: "mob/",
208-
StashName: "mob-stash-name",
209-
ResetDeleteRemoteWipBranch: false,
192+
CliName: "mob",
193+
RemoteName: "origin",
194+
WipCommitMessage: "mob next [ci-skip] [ci skip] [skip ci]",
195+
StartCommitMessage: "mob start [ci-skip] [ci skip] [skip ci]",
196+
SkipCiPushOptionEnabled: true,
197+
GitHooksEnabled: false,
198+
VoiceCommand: voiceCommand,
199+
VoiceMessage: "mob next",
200+
NotifyCommand: notifyCommand,
201+
NotifyMessage: "mob next",
202+
NextStay: true,
203+
RequireCommitMessage: false,
204+
HandleUncommittedChanges: FailWithError,
205+
StartCreate: false,
206+
WipBranchQualifier: "",
207+
WipBranchQualifierSeparator: "-",
208+
DoneSquash: Squash,
209+
OpenCommand: "",
210+
Timer: "",
211+
TimerLocal: true,
212+
TimerRoom: "",
213+
TimerUser: "",
214+
TimerUrl: "https://timer.mob.sh/",
215+
WipBranchPrefix: "mob/",
216+
StashName: "mob-stash-name",
217+
ResetDeleteRemoteWipBranch: false,
210218
}
211219
}
212220

configuration/configuration_test.go

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,56 @@ func TestParseArgsStartRoom(t *testing.T) {
103103
test.Equals(t, "testroom", configuration.TimerRoom)
104104
}
105105

106+
func TestDefaultConfigurationHandleUncommitedChanges(t *testing.T) {
107+
configuration := GetDefaultConfiguration()
108+
109+
command, parameters, configuration := ParseArgs([]string{"mob", "start"}, configuration)
110+
111+
test.Equals(t, "start", command)
112+
test.Equals(t, 0, len(parameters))
113+
test.Equals(t, FailWithError, configuration.HandleUncommittedChanges)
114+
}
115+
116+
func TestParseArgsIncludeUncommitedChanges(t *testing.T) {
117+
configuration := GetDefaultConfiguration()
118+
119+
command, parameters, configuration := ParseArgs([]string{"mob", "start", "--include-uncommitted-changes"}, configuration)
120+
121+
test.Equals(t, "start", command)
122+
test.Equals(t, 0, len(parameters))
123+
test.Equals(t, IncludeChanges, configuration.HandleUncommittedChanges)
124+
}
125+
126+
func TestParseArgsIncludeUncommitedChangesShort(t *testing.T) {
127+
configuration := GetDefaultConfiguration()
128+
129+
command, parameters, configuration := ParseArgs([]string{"mob", "start", "-i"}, configuration)
130+
131+
test.Equals(t, "start", command)
132+
test.Equals(t, 0, len(parameters))
133+
test.Equals(t, IncludeChanges, configuration.HandleUncommittedChanges)
134+
}
135+
136+
func TestParseArgsDiscardUncommitedChanges(t *testing.T) {
137+
configuration := GetDefaultConfiguration()
138+
139+
command, parameters, configuration := ParseArgs([]string{"mob", "start", "--discard-uncommitted-changes"}, configuration)
140+
141+
test.Equals(t, "start", command)
142+
test.Equals(t, 0, len(parameters))
143+
test.Equals(t, DiscardChanges, configuration.HandleUncommittedChanges)
144+
}
145+
146+
func TestParseArgsDiscardUncommitedChangesShort(t *testing.T) {
147+
configuration := GetDefaultConfiguration()
148+
149+
command, parameters, configuration := ParseArgs([]string{"mob", "start", "-d"}, configuration)
150+
151+
test.Equals(t, "start", command)
152+
test.Equals(t, 0, len(parameters))
153+
test.Equals(t, DiscardChanges, configuration.HandleUncommittedChanges)
154+
}
155+
106156
func TestParseArgsTimerRoom(t *testing.T) {
107157
configuration := GetDefaultConfiguration()
108158
test.Equals(t, configuration.WipBranchQualifier, "")
@@ -188,10 +238,6 @@ func (c Configuration) GetMobDoneSquash() string {
188238
return c.DoneSquash
189239
}
190240

191-
func (c Configuration) GetMobStartIncludeUncommittedChanges() bool {
192-
return c.StartIncludeUncommittedChanges
193-
}
194-
195241
func (c Configuration) GetMobStartCreateRemoteBranch() bool {
196242
return c.StartCreate
197243
}

mob.go

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
)
2222

2323
const (
24-
versionNumber = "5.2.0"
24+
versionNumber = "5.3.0"
2525
minimumGitVersion = "2.13.0"
2626
)
2727

@@ -527,7 +527,7 @@ func deleteRemoteWipBranch(configuration config.Configuration) {
527527

528528
func start(configuration config.Configuration) error {
529529
uncommittedChanges := hasUncommittedChanges()
530-
if uncommittedChanges && !configuration.StartIncludeUncommittedChanges {
530+
if uncommittedChanges && configuration.HandleUncommittedChanges == config.FailWithError {
531531
say.Info("cannot start; clean working tree required")
532532
sayUnstagedChangesInfo()
533533
sayUntrackedFilesInfo()
@@ -557,13 +557,16 @@ func start(configuration config.Configuration) error {
557557
return errors.New("cannot start; unpushed changes on base branch must be pushed upstream")
558558
}
559559

560-
if uncommittedChanges && silentgit("ls-tree", "-r", "HEAD", "--full-name", "--name-only", ".") == "" {
561-
say.Error("cannot start; current working dir is an uncommitted subdir")
562-
say.Fix("to fix this, go to the parent directory and try again", "cd ..")
563-
return errors.New("cannot start; current working dir is an uncommitted subdir")
560+
if uncommittedChanges && configuration.HandleUncommittedChanges == config.DiscardChanges {
561+
git("reset", "--hard")
564562
}
565563

566-
if uncommittedChanges {
564+
if uncommittedChanges && configuration.HandleUncommittedChanges == config.IncludeChanges {
565+
if silentgit("ls-tree", "-r", "HEAD", "--full-name", "--name-only", ".") == "" {
566+
say.Error("cannot start; current working dir is an uncommitted subdir")
567+
say.Fix("to fix this, go to the parent directory and try again", "cd ..")
568+
return errors.New("cannot start; current working dir is an uncommitted subdir")
569+
}
567570
git("stash", "push", "--include-untracked", "--message", configuration.StashName)
568571
say.Info("uncommitted changes were stashed. If an error occurs later on, you can recover them with 'git stash pop'.")
569572
}
@@ -580,7 +583,7 @@ func start(configuration config.Configuration) error {
580583
startNewMobSession(configuration)
581584
}
582585

583-
if uncommittedChanges && configuration.StartIncludeUncommittedChanges {
586+
if uncommittedChanges && configuration.HandleUncommittedChanges == config.IncludeChanges {
584587
stashes := silentgit("stash", "list")
585588
stash := findStashByName(stashes, configuration.StashName)
586589
git("stash", "pop", stash)
@@ -595,16 +598,22 @@ func start(configuration config.Configuration) error {
595598
}
596599

597600
func sayFixUncommittedChanges(configuration config.Configuration) {
598-
var instruction string
601+
var instructionInclude string
602+
var instructionDiscard string
599603
if configuration.StartCreate {
600-
instruction = "To start, including uncommitted changes and create the remote branch, use"
604+
instructionInclude = "To start, including uncommitted changes and create the remote branch, use"
605+
instructionDiscard = "To start, discarding uncommitted changes and create the remote branch, use"
601606
} else {
602-
instruction = "To start, including uncommitted changes, use"
607+
instructionInclude = "To start, including uncommitted changes, use"
608+
instructionDiscard = "To start, discarding uncommitted changes, use"
603609
}
604610

605-
fixCommand := configuration.CliName + " start" + createFix(configuration) + branchFix(configuration) + " --include-uncommitted-changes"
611+
fixCommandStart := configuration.CliName + " start" + createFix(configuration) + branchFix(configuration)
612+
fixCommandInclude := fixCommandStart + " --include-uncommitted-changes"
613+
fixCommandDiscard := fixCommandStart + " --discard-uncommitted-changes"
606614

607-
say.Fix(instruction, fixCommand)
615+
say.Fix(instructionInclude, fixCommandInclude)
616+
say.Fix(instructionDiscard, fixCommandDiscard)
608617
}
609618

610619
func createFix(configuration config.Configuration) string {

mob_test.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -532,19 +532,20 @@ func TestCleanMissingBaseBranch(t *testing.T) {
532532

533533
func TestStartUnstagedChanges(t *testing.T) {
534534
output, configuration := setup(t)
535-
configuration.StartIncludeUncommittedChanges = false
535+
configuration.HandleUncommittedChanges = config.FailWithError
536536
createFile(t, "test.txt", "contentIrrelevant")
537537

538538
start(configuration)
539539

540540
assertOnBranch(t, "master")
541541
assertNoMobSessionBranches(t, configuration, "mob-session")
542542
assertOutputContains(t, output, "mob start --include-uncommitted-changes")
543+
assertOutputContains(t, output, "mob start --discard-uncommitted-changes")
543544
}
544545

545546
func TestStartIncludeUnstagedChanges(t *testing.T) {
546547
_, configuration := setup(t)
547-
configuration.StartIncludeUncommittedChanges = true
548+
configuration.HandleUncommittedChanges = config.IncludeChanges
548549
createFile(t, "test.txt", "contentIrrelevant")
549550

550551
start(configuration)
@@ -553,9 +554,21 @@ func TestStartIncludeUnstagedChanges(t *testing.T) {
553554
assertMobSessionBranches(t, configuration, "mob-session")
554555
}
555556

557+
func TestStartDiscardUnstagedChanges(t *testing.T) {
558+
_, configuration := setup(t)
559+
configuration.HandleUncommittedChanges = config.DiscardChanges
560+
createFile(t, "test.txt", "contentIrrelevant")
561+
562+
start(configuration)
563+
564+
assertOnBranch(t, "mob-session")
565+
assertMobSessionBranches(t, configuration, "mob-session")
566+
assertCleanGitStatus(t)
567+
}
568+
556569
func TestStartIncludeUnstagedChangesInNewWorkingDirectory(t *testing.T) {
557570
output, configuration := setup(t)
558-
configuration.StartIncludeUncommittedChanges = true
571+
configuration.HandleUncommittedChanges = config.IncludeChanges
559572
createDirectory(t, "subdirnew")
560573
setWorkingDir(tempDir + "/local/subdirnew")
561574
createFile(t, "test.txt", "contentIrrelevant")
@@ -587,7 +600,7 @@ func TestBranch(t *testing.T) {
587600

588601
func TestStartIncludeUntrackedFiles(t *testing.T) {
589602
_, configuration := setup(t)
590-
configuration.StartIncludeUncommittedChanges = true
603+
configuration.HandleUncommittedChanges = config.IncludeChanges
591604
createFile(t, "example.txt", "contentIrrelevant")
592605

593606
start(configuration)
@@ -597,7 +610,7 @@ func TestStartIncludeUntrackedFiles(t *testing.T) {
597610

598611
func TestStartUntrackedFiles(t *testing.T) {
599612
_, configuration := setup(t)
600-
configuration.StartIncludeUncommittedChanges = false
613+
configuration.HandleUncommittedChanges = config.FailWithError
601614
createFile(t, "example.txt", "contentIrrelevant")
602615

603616
start(configuration)
@@ -625,6 +638,7 @@ func TestStartOnUnpushedFeatureBranchWithUncommitedChanges(t *testing.T) {
625638

626639
assertOnBranch(t, "feature1")
627640
assertOutputContains(t, output, "mob start --include-uncommitted-changes")
641+
assertOutputContains(t, output, "mob start --discard-uncommitted-changes")
628642
}
629643

630644
func TestStartCreateOnUnpushedFeatureBranch(t *testing.T) {
@@ -660,6 +674,7 @@ func TestStartCreateOnUnpushedFeatureBranchWithUncommitedChanges(t *testing.T) {
660674

661675
assertOutputContains(t, output, "To start, including uncommitted changes and create the remote branch, use")
662676
assertOutputContains(t, output, "mob start --create --include-uncommitted-changes")
677+
assertOutputContains(t, output, "mob start --create --discard-uncommitted-changes")
663678
}
664679

665680
func TestStartCreateIncludeUncommitedChangesOnUnpushedFeatureBranchWithUncommitedChanges(t *testing.T) {
@@ -668,7 +683,7 @@ func TestStartCreateIncludeUncommitedChangesOnUnpushedFeatureBranchWithUncommite
668683
createFile(t, "file.txt", "contentIrrelevant")
669684

670685
configuration.StartCreate = true
671-
configuration.StartIncludeUncommittedChanges = true
686+
configuration.HandleUncommittedChanges = config.IncludeChanges
672687
start(configuration)
673688

674689
assertOnBranch(t, "mob/feature1")
@@ -680,7 +695,7 @@ func TestStartCreateIncludeUncommitedChangesOnUnpushedFeatureBranchWithUncommite
680695
createFile(t, "file.txt", "contentIrrelevant")
681696

682697
configuration.StartCreate = true
683-
configuration.StartIncludeUncommittedChanges = true
698+
configuration.HandleUncommittedChanges = config.IncludeChanges
684699
configuration.WipBranchQualifier = "green"
685700
start(configuration)
686701

@@ -1521,6 +1536,7 @@ func TestStartBranchWithUncommitedChangesFixWithBranch(t *testing.T) {
15211536
runMob(t, tempDir+"/local", "start", "-b", "green")
15221537

15231538
assertOutputContains(t, output, "mob start --branch green --include-uncommitted-changes")
1539+
assertOutputContains(t, output, "mob start --branch green --discard-uncommitted-changes")
15241540
resetExit()
15251541
}
15261542

@@ -1534,6 +1550,7 @@ func TestStartBranchEnvWithUncommitedChangesFixWithoutBranch(t *testing.T) {
15341550
runMob(t, tempDir+"/local", "start")
15351551

15361552
assertOutputContains(t, output, "mob start --include-uncommitted-changes")
1553+
assertOutputContains(t, output, "mob start --discard-uncommitted-changes")
15371554
resetExit()
15381555
}
15391556

@@ -1548,6 +1565,7 @@ func TestStartCreateBranchWithUncommitedChangesFixWithBranch(t *testing.T) {
15481565
runMob(t, tempDir+"/local", "start", "--create", "-b", "green")
15491566

15501567
assertOutputContains(t, output, "mob start --create --branch green --include-uncommitted-changes")
1568+
assertOutputContains(t, output, "mob start --create --branch green --discard-uncommitted-changes")
15511569
resetExit()
15521570
}
15531571

@@ -1563,6 +1581,7 @@ func TestStartCreateBranchEnvWithUncommitedChangesFixWithoutBranch(t *testing.T)
15631581

15641582
os.Unsetenv("MOB_WIP_BRANCH_QUALIFIER")
15651583
assertOutputContains(t, output, "mob start --create --include-uncommitted-changes")
1584+
assertOutputContains(t, output, "mob start --create --discard-uncommitted-changes")
15661585
resetExit()
15671586
}
15681587

0 commit comments

Comments
 (0)