@@ -77,5 +77,80 @@ public void PushingABranchThatDoesNotTrackAnUpstreamBranchThrows()
77
77
repo . Network . Push ( branch ) ;
78
78
} ) ) ;
79
79
}
80
+
81
+ [ Fact ]
82
+ public void CanForcePush ( )
83
+ {
84
+ string remoteRepoPath = InitNewRepository ( true ) ;
85
+
86
+ // Create a new repository
87
+ string localRepoPath = InitNewRepository ( ) ;
88
+ using ( var localRepo = new Repository ( localRepoPath ) )
89
+ {
90
+ // Add a commit
91
+ Commit first = AddCommitToRepo ( localRepo ) ;
92
+
93
+ Remote remote = localRepo . Network . Remotes . Add ( "origin" , remoteRepoPath ) ;
94
+
95
+ localRepo . Branches . Update ( localRepo . Head ,
96
+ b => b . Remote = remote . Name ,
97
+ b => b . UpstreamBranch = localRepo . Head . CanonicalName ) ;
98
+
99
+ // Push this commit
100
+ localRepo . Network . Push ( localRepo . Head ) ;
101
+ AssertRemoteHeadTipEquals ( localRepo , first . Sha ) ;
102
+
103
+ UpdateTheRemoteRepositoryWithANewCommit ( remoteRepoPath ) ;
104
+
105
+ // Add another commit
106
+ Commit second = AddCommitToRepo ( localRepo ) ;
107
+
108
+ // Try to fast forward push this new commit
109
+ Assert . Throws < NonFastForwardException > ( ( ) => localRepo . Network . Push ( localRepo . Head ) ) ;
110
+
111
+ // Force push the new commit
112
+ string pushRefSpec = string . Format ( "+{0}:{0}" , localRepo . Head . CanonicalName ) ;
113
+ localRepo . Network . Push ( localRepo . Network . Remotes . Single ( ) , pushRefSpec ) ;
114
+
115
+ AssertRemoteHeadTipEquals ( localRepo , second . Sha ) ;
116
+ }
117
+ }
118
+
119
+ private static void AssertRemoteHeadTipEquals ( Repository localRepo , string sha )
120
+ {
121
+ var remoteReferences = localRepo . Network . ListReferences ( localRepo . Network . Remotes . Single ( ) ) ;
122
+ DirectReference remoteHead = remoteReferences . Single ( r => r . CanonicalName == "HEAD" ) ;
123
+
124
+ Assert . Equal ( sha , remoteHead . TargetIdentifier ) ;
125
+ }
126
+
127
+ private void UpdateTheRemoteRepositoryWithANewCommit ( string remoteRepoPath )
128
+ {
129
+ // Perform a fresh clone of the upstream repository
130
+ var scd = BuildSelfCleaningDirectory ( ) ;
131
+ string clonedRepoPath = Repository . Clone ( remoteRepoPath , scd . DirectoryPath ) ;
132
+
133
+ using ( var clonedRepo = new Repository ( clonedRepoPath ) )
134
+ {
135
+ // Add a commit
136
+ AddCommitToRepo ( clonedRepo ) ;
137
+
138
+ // Push this new commit toward an upstream repository
139
+ clonedRepo . Network . Push ( clonedRepo . Head ) ;
140
+ }
141
+ }
142
+
143
+ private Commit AddCommitToRepo ( Repository repository )
144
+ {
145
+
146
+ string random = Guid . NewGuid ( ) . ToString ( ) ;
147
+ string filename = random + ".txt" ;
148
+
149
+ Touch ( repository . Info . WorkingDirectory , filename , random ) ;
150
+
151
+ repository . Index . Stage ( filename ) ;
152
+
153
+ return repository . Commit ( "New commit" , Constants . Signature , Constants . Signature ) ;
154
+ }
80
155
}
81
156
}
0 commit comments