docs: def commit(ctx, f, force_yes, date):
      """
      Commits your work to the server. The [date] option can be used either as a
      single date (eg. 20.01.2014), as a range (eg. 20.01.2014-22.01.2014), or as
      a range with one of the dates omitted (eg. -22.01.2014).
      """
      timesheet_collection = get_timesheet_collection_for_context(ctx, f)
  
      if not date and not force_yes:
          non_workday_entries = timesheet_collection.entries.filter(ignored=False, pushed=False, current_workday=False)
  
          if non_workday_entries:
              if not ctx.obj['view'].confirm_commit_entries(non_workday_entries):
                  ctx.obj['view'].msg("Ok then.")
                  return
  
      ctx.obj['view'].pushing_entries()
      backends_entries = defaultdict(list)
  
      try:
          # Push entries
          for timesheet in timesheet_collection.timesheets:
              entries_to_push = get_entries_to_push(
                  timesheet, date, ctx.obj['settings']['regroup_entries']
              )
  
              for (entries_date, entries) in entries_to_push.items():
                  for entry in entries:
                      backend_name = aliases_database[entry.alias].backend
                      backend = plugins_registry.get_backend(backend_name)
                      backends_entries[backend].append(entry)
  
                      try:
                          additional_info = backend.push_entry(entries_date, entry)
                      except KeyboardInterrupt:
                          entry.push_error = ("Interrupted, check status in"
                                              " backend")
                          raise
                      except Exception as e:
                          additional_info = None
                          entry.push_error = six.text_type(e)
                      else:
                          entry.push_error = None
                      finally:
                          ctx.obj['view'].pushed_entry(entry, additional_info)
  
          # Call post_push_entries on backends
          backends_post_push(backends_entries)
      except KeyboardInterrupt:
          pass
      finally:
          comment_timesheets_entries(timesheet_collection, date)
  
      ignored_entries = timesheet_collection.entries.filter(date=date, ignored=True, unmapped=False, pushed=False)
      ignored_entries_list = []
      for (entries_date, entries) in six.iteritems(ignored_entries):
          ignored_entries_list.extend(entries)
  
      all_entries = itertools.chain(*backends_entries.values())
      ctx.obj['view'].pushed_entries_summary(list(all_entries),
                                             ignored_entries_list)