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)
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).