What ISession.Flush() generally does
ISession.Flush() updates OO side changes to the framework but not to the database; this has at least the following effects
1. Internal flags change so that IsDirty() is always set to false
2. updates internal flags/states of the framework so that it's consistent with the OO model
Internal state related to IsDirty() changes as the OO side changes as NHibernate has wrappers and some other unknown constructs that work closely with entities and keep track of their changes, so although it's still far from enough for NHibernate to be confirmed of changes and get the necessary detailed information of the changes, (and that's why methods like ISession.Delete(), ISession.Save() are needed) it at least is able to know of the existence of the changes whenever changes are made.
Advantages of Flush
By using ISession.Flush(), you can be sure that all changes are made done to the persistence framework but not to the underlying database, so you can at any time choose to either commit the changes to Database or totally cancel all the changes made since last checkpoint by doing a NHibernate rollback (note: for rolling back, the OO side needs to be restored to the point where the transaction started accordingly)
Confusion of IsDirty()
A natural misconception about IsDirty() is that it can be alone used as an indicator of whether the model has been changed. Unfortunately if used improperly it might be totally against this use.
From the discussion above, we can see that IsDirty() is changed to true (indicating a change) whenever OO model is changed without flush; in this sense, this method (and its underlying flags) might be sensitive enough to detect changes (need further proof and verification), but if it is used in a untimely manner with flush which may flip its value and may be used anywhere proper for update purpose mentioned above, the program will get a result totally contrary to what it's supposed to be. So the best approach might be using it in a combination with another set of internal constructs kept in your application in accordance to your own business logic to form a correct answer. And also be even more careful when using with advanced application features such as change management and undo/redo capabilities.
Reattachment Problem
If an entity is removed from the OO model it used to be part of as well as detached from the persistence by being called on with ISession.Delete(); and immediately afterwards it is added back in the same model (at the same place or not), and invoked with ISession.Save(), an issue may come up. The primary reason is NH framework was not properly updated upon the deletion before it could accept an addition of the same object. The solution is either do a commit or a flush before the adding operation. And the selection between these two is depending on whether you want it to be updated to the database.